priv/main/vex_globals.h \
priv/main/vex_util.h \
priv/guest-generic/g_generic_x87.h \
+ priv/guest-generic/bb_to_IR.h \
priv/guest-x86/gdefs.h \
priv/guest-amd64/gdefs.h \
priv/guest-arm/gdefs.h \
priv/host-generic/h_generic_simd64.o \
priv/host-generic/reg_alloc2.o \
priv/guest-generic/g_generic_x87.o \
+ priv/guest-generic/bb_to_IR.o \
priv/guest-x86/ghelpers.o \
priv/guest-amd64/ghelpers.o \
priv/guest-arm/ghelpers.o \
$(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/guest-generic/g_generic_x87.o \
-c priv/guest-generic/g_generic_x87.c
+priv/guest-generic/bb_to_IR.o: $(ALL_HEADERS) priv/guest-generic/bb_to_IR.c
+ $(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/guest-generic/bb_to_IR.o \
+ -c priv/guest-generic/bb_to_IR.c
+
priv/guest-x86/ghelpers.o: $(ALL_HEADERS) priv/guest-x86/ghelpers.c
$(CC) $(CCFLAGS) $(ALL_INCLUDES) -o priv/guest-x86/ghelpers.o \
-c priv/guest-x86/ghelpers.c
/*--- amd64 to IR conversion ---*/
/*---------------------------------------------------------*/
+/* Convert one amd64 insn to IR. See the type DisOneInstrFn in
+ bb_to_IR.h. */
extern
-IRBB* bbToIR_AMD64 ( UChar* amd64code,
- Addr64 guest_rip_start,
- VexGuestExtents* vge,
- Bool (*byte_accessible)(Addr64),
- Bool (*resteerOkFn)(Addr64),
- Bool host_bigendian,
- VexArchInfo* archinfo_guest );
+DisResult disInstr_AMD64 ( IRBB* irbb,
+ Bool put_IP,
+ Bool (*resteerOkFn) ( Addr64 ),
+ UChar* guest_code,
+ Long delta,
+ Addr64 guest_IP,
+ VexArchInfo* archinfo,
+ Bool host_bigendian );
/* Used by the optimiser to specialise calls to helpers. */
extern
#include "libvex.h"
#include "main/vex_util.h"
+#include "guest-generic/bb_to_IR.h"
#include "guest-amd64/gdefs.h"
#include "guest-generic/g_generic_x87.h"
#include "main/vex_util.h"
#include "main/vex_globals.h"
+#include "guest-generic/bb_to_IR.h"
#include "guest-amd64/gdefs.h"
/*--- Globals ---*/
/*------------------------------------------------------------*/
-/* ------ CONST for entire BB ------ */
+/* These are set at the start of the translation of an insn, right
+ down in disInstr_AMD64, so that we don't have to pass them around
+ endlessly. They are all constant during the translation of any
+ given insn. */
/* These are set at the start of the translation of a BB, so
that we don't have to pass them around endlessly. */
/* We need to know this to do sub-register accesses correctly. */
-/* CONST for entire BB */
static Bool host_is_bigendian;
-/* Pointer to the guest code area. */
-/* CONST for entire BB */
+/* Pointer to the guest code area (points to start of BB, not to the
+ insn being processed). */
static UChar* guest_code;
/* The guest address corresponding to guest_code[0]. */
-/* CONST for entire BB */
-static Addr64 guest_rip_bbstart;
-
-/* The IRBB* into which we're generating code. */
-/* CONST for entire BB */
-static IRBB* irbb;
-
-
-/* ------ CONST for each instruction ------ */
+static Addr64 guest_RIP_bbstart;
/* The guest address for the instruction currently being
translated. */
-/* CONST for any specific insn, not for the entire BB */
-static Addr64 guest_rip_curr_instr;
-
-/* Emergency verboseness just for this insn? DEBUG ONLY */
-static Bool insn_verbose = False;
+static Addr64 guest_RIP_curr_instr;
+/* The IRBB* into which we're generating code. */
+static IRBB* irbb;
/* For ensuring that %rip-relative addressing is done right. A read
of %rip generates the address of the next instruction. It may be
After the decode, if _mustcheck is now True, _assumed is
checked. */
-static Addr64 guest_rip_next_assumed;
-static Bool guest_rip_next_mustcheck;
+static Addr64 guest_RIP_next_assumed;
+static Bool guest_RIP_next_mustcheck;
/*------------------------------------------------------------*/
}
#define DIP(format, args...) \
- if (insn_verbose || (vex_traceflags & VEX_TRACE_FE)) \
+ if (vex_traceflags & VEX_TRACE_FE) \
vex_printf(format, ## args)
#define DIS(buf, format, args...) \
- if (insn_verbose || (vex_traceflags & VEX_TRACE_FE)) \
+ if (vex_traceflags & VEX_TRACE_FE) \
vex_sprintf(buf, format, ## args)
#define OFFB_EMWARN offsetof(VexGuestAMD64State,guest_EMWARN)
-/*------------------------------------------------------------*/
-/*--- Disassemble an entire basic block ---*/
-/*------------------------------------------------------------*/
-
-/* The results of disassembling an instruction. There are three
- possible outcomes. For Dis_Resteer, the disassembler _must_
- continue at the specified address. For Dis_StopHere, the
- disassembler _must_ terminate the BB. For Dis_Continue, we may at
- our option either disassemble the next insn, or terminate the BB;
- but in the latter case we must set the bb's ->next field to point
- to the next instruction. */
-
-typedef
- enum {
- Dis_StopHere, /* this insn terminates the BB; we must stop. */
- Dis_Continue, /* we can optionally continue into the next insn */
- Dis_Resteer /* followed a branch; continue at the spec'd addr */
- }
- DisResult;
-
-
-/* forward decls .. */
-//.. static IRExpr* mkU32 ( UInt i );
-//.. static void stmt ( IRStmt* st );
-//..
-//..
-/* disInstr disassembles an instruction located at &guest_code[delta],
- and sets *size to its size. If the returned value is Dis_Resteer,
- the next guest address is assigned to *whereNext. disInstr is not
- permitted to return Dis_Resteer if either (1) resteerOK is False,
- or (2) resteerOkFn, when applied to the address which it wishes to
- resteer into, returns False. */
-
-static
-DisResult disInstr ( /*IN*/ Bool resteerOK,
- /*IN*/ Bool (*resteerOkFn) ( Addr64 ),
- /*IN*/ ULong delta,
- /*IN*/ VexArchInfo* archinfo,
- /*OUT*/ Long* size,
- /*OUT*/ Addr64* whereNext );
-
-
-/* This is the main (only, in fact) entry point for this module. */
-
-/* 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_AMD64 ( UChar* amd64code,
- Addr64 guest_rip_start,
- VexGuestExtents* vge,
- Bool (*byte_accessible)(Addr64),
- Bool (*chase_into_ok)(Addr64),
- Bool host_bigendian,
- VexArchInfo* archinfo_guest )
-{
- Long delta, size;
- Int i, n_instrs, first_stmt_idx;
- Addr64 guest_next;
- Bool resteerOK;
- DisResult dres;
- IRStmt* imark;
- static Int n_resteers = 0;
- Int d_resteers = 0;
-
- /* check sanity .. */
- vassert(vex_control.guest_max_insns >= 1);
- 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(archinfo_guest->subarch == VexSubArch_NONE);
-
- /* Start a new, empty extent. */
- vge->n_used = 1;
- vge->base[0] = guest_rip_start;
- vge->len[0] = 0;
-
- /* Set up globals. */
- host_is_bigendian = host_bigendian;
- guest_code = amd64code;
- guest_rip_bbstart = guest_rip_start;
- irbb = emptyIRBB();
- insn_verbose = False;
-
- /* Delta keeps track of how far along the amd64code array we
- have so far gone. */
- delta = 0;
- n_instrs = 0;
-
- while (True) {
- vassert(n_instrs < vex_control.guest_max_insns);
-
- guest_next = 0;
- resteerOK
- = toBool(
- 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
- );
-
- /* This is the %RIP of the instruction we're just about to deal
- with. */
- guest_rip_curr_instr = guest_rip_bbstart + delta;
-
- /* This is the irbb statement array index of the first stmt in
- this insn. That will always be the instruction-mark
- descriptor. */
- first_stmt_idx = irbb->stmts_used;
-
- /* Add an instruction-mark statement. We won't know until after
- disInstr how long the instruction is, so just put in a zero
- length and we'll fix it up later. */
- stmt( IRStmt_IMark( guest_rip_curr_instr, 0 ));
-
- if (n_instrs > 0) {
- /* for the first insn, the dispatch loop will have set
- %RIP, but for all the others we have to do it ourselves. */
- stmt( IRStmt_Put( OFFB_RIP, mkU64(guest_rip_curr_instr)) );
- }
-
- /* Do the instruction. This may set insn_verbose to True, which
- needs to be annulled. */
- size = 0; /* just in case disInstr doesn't set it */
- guest_rip_next_assumed = 0;
- guest_rip_next_mustcheck = False;
- dres = disInstr( resteerOK, chase_into_ok,
- delta, archinfo_guest, &size, &guest_next );
- insn_verbose = False;
-
- /* stay sane ... */
- vassert(size >= 0 && size <= 18);
-
- /* Fill in the insn-mark length field. */
- vassert(first_stmt_idx >= 0 && first_stmt_idx < irbb->stmts_used);
- imark = irbb->stmts[first_stmt_idx];
- vassert(imark);
- vassert(imark->tag == Ist_IMark);
- vassert(imark->Ist.IMark.len == 0);
- imark->Ist.IMark.len = toUInt(size);
-
- /* Print the resulting IR, if needed. */
- if (vex_traceflags & VEX_TRACE_FE) {
- for (i = first_stmt_idx; i < irbb->stmts_used; i++) {
- vex_printf(" ");
- ppIRStmt(irbb->stmts[i]);
- vex_printf("\n");
- }
- }
-
- /* If disInstr tried to figure out the next rip, check it got it
- right. Failure of this assertion is serious and denotes a
- bug in disInstr. */
- if (guest_rip_next_mustcheck
- && guest_rip_next_assumed != guest_rip_curr_instr+size) {
- vex_printf("\n");
- vex_printf("assumed next %%rip = 0x%llx\n",
- guest_rip_next_assumed );
- vex_printf(" actual next %%rip = 0x%llx\n",
- guest_rip_curr_instr+size );
- vpanic("bbToIR_AMD64: disInstr miscalculated next %rip");
- }
-
- if (dres == Dis_StopHere) {
- vassert(irbb->next != NULL);
- if (vex_traceflags & VEX_TRACE_FE) {
- vex_printf(" ");
- vex_printf( "goto {");
- ppIRJumpKind(irbb->jumpkind);
- vex_printf( "} ");
- ppIRExpr( irbb->next );
- vex_printf( "\n");
- }
- }
-
- delta += size;
- /* If vex_control.guest_max_insns is required to be < 500 and
- each insn is at max 15 bytes long, this limit of 10000 then
- seems reasonable since the max possible extent length will be
- 500 * 15 == 7500. */
- vassert(vge->len[vge->n_used-1] < 10000);
- vge->len[vge->n_used-1]
- = toUShort(toUInt( vge->len[vge->n_used-1] + size ));
- n_instrs++;
- DIP("\n");
-
- if (!resteerOK)
- vassert(dres != Dis_Resteer);
- if (dres != Dis_Resteer)
- vassert(guest_next == 0);
-
- switch (dres) {
- case Dis_Continue:
- vassert(irbb->next == NULL);
- if (n_instrs < vex_control.guest_max_insns) {
- /* keep going */
- } else {
- irbb->next = mkU64(guest_rip_start+delta);
- return irbb;
- }
- break;
- case Dis_StopHere:
- vassert(irbb->next != NULL);
- return irbb;
- case Dis_Resteer:
- vassert(irbb->next == NULL);
- /* figure out a new delta to continue at. */
- vassert(chase_into_ok(guest_next));
- delta = guest_next - guest_rip_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)
- vex_printf("resteer[%d,%d] to 0x%llx (delta = %lld)\n",
- n_resteers, d_resteers,
- guest_next, delta);
- break;
- }
- }
-}
-
-
/*------------------------------------------------------------*/
/*--- Helper bits and pieces for deconstructing the ---*/
/*--- amd64 insn stream. ---*/
case 0x1C: case 0x1D: case 0x1E: case 0x1F:
vpanic("disAMode(amd64): not an addr!");
- /* RIP + disp32. This assumes that guest_rip_curr_instr is set
+ /* RIP + disp32. This assumes that guest_RIP_curr_instr is set
correctly at the start of handling each instruction. */
case 0x05:
{ Long d = getSDisp32(delta);
the top-level driver logic (bbToIR_AMD64) to check we
guessed right, after the instruction is completely
decoded. */
- guest_rip_next_mustcheck = True;
- guest_rip_next_assumed = guest_rip_bbstart
+ guest_RIP_next_mustcheck = True;
+ guest_RIP_next_assumed = guest_RIP_bbstart
+ delta+4 + extra_bytes;
return disAMode_copy2tmp(
handleSegOverride(pfx,
- binop(Iop_Add64, mkU64(guest_rip_next_assumed),
+ binop(Iop_Add64, mkU64(guest_RIP_next_assumed),
mkU64(d))));
}
/* Group 5 extended opcodes. */
static
-ULong dis_Grp5 ( Prefix pfx, Int sz, ULong delta, DisResult* whatNext )
+ULong dis_Grp5 ( Prefix pfx, Int sz, ULong delta, DisResult* dres )
{
Int len;
UChar modrm;
t2 = newTemp(Ity_I64);
assign(t2, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8)));
putIReg64(R_RSP, mkexpr(t2));
- storeLE( mkexpr(t2), mkU64(guest_rip_bbstart+delta+1));
+ storeLE( mkexpr(t2), mkU64(guest_RIP_bbstart+delta+1));
make_redzone_AbiHint(t2, "call-Ev(reg)");
jmp_treg(Ijk_Call,t3);
- *whatNext = Dis_StopHere;
+ dres->whatNext = Dis_StopHere;
showSz = False;
break;
case 4: /* jmp Ev */
t3 = newTemp(Ity_I64);
assign(t3, getIRegE(sz,pfx,modrm));
jmp_treg(Ijk_Boring,t3);
- *whatNext = Dis_StopHere;
+ dres->whatNext = Dis_StopHere;
showSz = False;
break;
default:
t2 = newTemp(Ity_I64);
assign(t2, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8)));
putIReg64(R_RSP, mkexpr(t2));
- storeLE( mkexpr(t2), mkU64(guest_rip_bbstart+delta+len));
+ storeLE( mkexpr(t2), mkU64(guest_RIP_bbstart+delta+len));
make_redzone_AbiHint(t2, "call-Ev(mem)");
jmp_treg(Ijk_Call,t3);
- *whatNext = Dis_StopHere;
+ dres->whatNext = Dis_StopHere;
showSz = False;
break;
case 4: /* JMP Ev */
t3 = newTemp(Ity_I64);
assign(t3, loadLE(Ity_I64,mkexpr(addr)));
jmp_treg(Ijk_Boring,t3);
- *whatNext = Dis_StopHere;
+ dres->whatNext = Dis_StopHere;
showSz = False;
break;
case 6: /* PUSH Ev */
IRStmt_Exit(
binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
Ijk_EmWarn,
- IRConst_U64( guest_rip_bbstart+delta )
+ IRConst_U64( guest_RIP_bbstart+delta )
)
);
IRStmt_Exit(
binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
Ijk_EmWarn,
- IRConst_U64( guest_rip_bbstart+delta )
+ IRConst_U64( guest_RIP_bbstart+delta )
)
);
break;
/*--- Disassemble a single instruction ---*/
/*------------------------------------------------------------*/
-/* Disassemble a single instruction into IR. The instruction
- is located in host memory at &guest_code[delta].
- Set *size to be the size of the instruction.
- If the returned value is Dis_Resteer,
- the next guest address is assigned to *whereNext. If resteerOK
- is False, disInstr may not return Dis_Resteer. */
+/* Disassemble a single instruction into IR. The instruction is
+ located in host memory at &guest_code[delta]. */
-static
-DisResult disInstr ( /*IN*/ Bool resteerOK,
- /*IN*/ Bool (*resteerOkFn) ( Addr64 ),
- /*IN*/ ULong delta,
- /*IN*/ VexArchInfo* archinfo,
- /*OUT*/ Long* size,
- /*OUT*/ Addr64* whereNext )
+static
+DisResult disInstr_AMD64_WRK (
+ Bool put_IP,
+ Bool (*resteerOkFn) ( Addr64 ),
+ Long delta64,
+ VexArchInfo* archinfo
+ )
{
IRType ty;
IRTemp addr, t0, t1, t2, t3, t4, t5, t6;
Long d64;
HChar dis_buf[50];
Int am_sz, d_sz, n, n_prefixes;
- DisResult whatNext = Dis_Continue;
+ DisResult dres;
UChar* insn; /* used in SSE decoders */
+ /* The running delta */
+ Long delta = delta64;
+
/* Holds eip at the start of the insn, so that we can print
consistent error messages for unimplemented insns. */
ULong delta_start = delta;
/* pfx holds the summary of prefixes. */
Prefix pfx = PFX_EMPTY;
- /* If we don't set *size properly, this causes bbToIR_AMD64Instr to
- assert. */
- *size = 0;
+ /* Set result defaults. */
+ dres.whatNext = Dis_Continue;
+ dres.len = 0;
+ dres.continueAt = 0;
- vassert(guest_rip_next_assumed == 0);
- vassert(guest_rip_next_mustcheck == False);
+ vassert(guest_RIP_next_assumed == 0);
+ vassert(guest_RIP_next_mustcheck == False);
addr = t0 = t1 = t2 = t3 = t4 = t5 = t6 = IRTemp_INVALID;
- DIP("\t0x%llx: ", guest_rip_bbstart+delta);
+ DIP("\t0x%llx: ", guest_RIP_bbstart+delta);
+
+ /* We may be asked to update the guest RIP before going further. */
+ if (put_IP)
+ stmt( IRStmt_Put( OFFB_RIP, mkU64(guest_RIP_curr_instr)) );
/* Spot the client-request magic sequence. */
{
) {
DIP("%%edx = client_request ( %%eax )\n");
delta += 18;
- jmp_lit(Ijk_ClientReq, guest_rip_bbstart+delta);
- whatNext = Dis_StopHere;
+ jmp_lit(Ijk_ClientReq, guest_RIP_bbstart+delta);
+ dres.whatNext = Dis_StopHere;
goto decode_success;
}
}
IRStmt_Exit(
binop(Iop_CmpNE64, unop(Iop_32Uto64,mkexpr(ew)), mkU64(0)),
Ijk_EmWarn,
- IRConst_U64(guest_rip_bbstart+delta)
+ IRConst_U64(guest_RIP_bbstart+delta)
)
);
goto decode_success;
if (haveF2(pfx)) goto decode_failure;
/* F3 is acceptable on AMD. */
dis_ret(0);
- whatNext = Dis_StopHere;
+ dres.whatNext = Dis_StopHere;
DIP(haveF3(pfx) ? "rep ; ret\n" : "ret\n");
break;
case 0xE8: /* CALL J4 */
if (haveF2orF3(pfx)) goto decode_failure;
d64 = getSDisp32(delta); delta += 4;
- d64 += (guest_rip_bbstart+delta);
- /* (guest_rip_bbstart+delta) == return-to addr, d64 == call-to addr */
+ d64 += (guest_RIP_bbstart+delta);
+ /* (guest_RIP_bbstart+delta) == return-to addr, d64 == call-to addr */
t1 = newTemp(Ity_I64);
assign(t1, binop(Iop_Sub64, getIReg64(R_RSP), mkU64(8)));
putIReg64(R_RSP, mkexpr(t1));
- storeLE( mkexpr(t1), mkU64(guest_rip_bbstart+delta));
+ storeLE( mkexpr(t1), mkU64(guest_RIP_bbstart+delta));
make_redzone_AbiHint(t1, "call-d32");
- if (resteerOK && resteerOkFn((Addr64)d64)) {
+ if (resteerOkFn((Addr64)d64)) {
/* follow into the call target. */
- whatNext = Dis_Resteer;
- *whereNext = d64;
+ dres.whatNext = Dis_Resteer;
+ dres.continueAt = d64;
} else {
jmp_lit(Ijk_Call,d64);
- whatNext = Dis_StopHere;
+ dres.whatNext = Dis_StopHere;
}
DIP("call 0x%llx\n",d64);
break;
if (haveF2orF3(pfx)) goto decode_failure;
if (sz != 4)
goto decode_failure; /* JRS added 2004 July 11 */
- d64 = (guest_rip_bbstart+delta+1) + getSDisp8(delta);
+ d64 = (guest_RIP_bbstart+delta+1) + getSDisp8(delta);
delta++;
- if (resteerOK && resteerOkFn(d64)) {
- whatNext = Dis_Resteer;
- *whereNext = d64;
+ if (resteerOkFn(d64)) {
+ dres.whatNext = Dis_Resteer;
+ dres.continueAt = d64;
} else {
jmp_lit(Ijk_Boring,d64);
- whatNext = Dis_StopHere;
+ dres.whatNext = Dis_StopHere;
}
DIP("jmp-8 0x%llx\n", d64);
break;
if (haveF2orF3(pfx)) goto decode_failure;
if (sz != 4)
goto decode_failure; /* JRS added 2004 July 11 */
- d64 = (guest_rip_bbstart+delta+sz) + getSDisp(sz,delta);
+ d64 = (guest_RIP_bbstart+delta+sz) + getSDisp(sz,delta);
delta += sz;
- if (resteerOK && resteerOkFn(d64)) {
- whatNext = Dis_Resteer;
- *whereNext = d64;
+ if (resteerOkFn(d64)) {
+ dres.whatNext = Dis_Resteer;
+ dres.continueAt = d64;
} else {
jmp_lit(Ijk_Boring,d64);
- whatNext = Dis_StopHere;
+ dres.whatNext = Dis_StopHere;
}
DIP("jmp 0x%llx\n", d64);
break;
case 0x7E: /* JLEb/JNGb (jump less or equal) */
case 0x7F: /* JGb/JNLEb (jump greater) */
if (haveF2orF3(pfx)) goto decode_failure;
- d64 = (guest_rip_bbstart+delta+1) + getSDisp8(delta);
+ d64 = (guest_RIP_bbstart+delta+1) + getSDisp8(delta);
delta++;
jcc_01( (AMD64Condcode)(opc - 0x70),
- guest_rip_bbstart+delta,
+ guest_RIP_bbstart+delta,
d64 );
- whatNext = Dis_StopHere;
+ dres.whatNext = Dis_StopHere;
DIP("j%s-8 0x%llx\n", name_AMD64Condcode(opc - 0x70), d64);
break;
if (opc == 0xAE)
sz = 1;
dis_REP_op ( AMD64CondNZ, dis_SCAS, sz,
- guest_rip_curr_instr,
- guest_rip_bbstart+delta, "repne scas", pfx );
- whatNext = Dis_StopHere;
+ guest_RIP_curr_instr,
+ guest_RIP_bbstart+delta, "repne scas", pfx );
+ dres.whatNext = Dis_StopHere;
break;
}
/* AE/AF: scasb/scas{w,l,q} */
if (opc == 0xA6)
sz = 1;
dis_REP_op ( AMD64CondZ, dis_CMPS, sz,
- guest_rip_curr_instr,
- guest_rip_bbstart+delta, "repe cmps", pfx );
- whatNext = Dis_StopHere;
+ guest_RIP_curr_instr,
+ guest_RIP_bbstart+delta, "repe cmps", pfx );
+ dres.whatNext = Dis_StopHere;
break;
}
goto decode_failure;
if (opc == 0xAA)
sz = 1;
dis_REP_op ( AMD64CondAlways, dis_STOS, sz,
- guest_rip_curr_instr,
- guest_rip_bbstart+delta, "rep stos", pfx );
- whatNext = Dis_StopHere;
+ guest_RIP_curr_instr,
+ guest_RIP_bbstart+delta, "rep stos", pfx );
+ dres.whatNext = Dis_StopHere;
break;
}
/* AA/AB: stosb/stos{w,l,q} */
if (opc == 0xA4)
sz = 1;
dis_REP_op ( AMD64CondAlways, dis_MOVS, sz,
- guest_rip_curr_instr,
- guest_rip_bbstart+delta, "rep movs", pfx );
- whatNext = Dis_StopHere;
+ guest_RIP_curr_instr,
+ guest_RIP_bbstart+delta, "rep movs", pfx );
+ dres.whatNext = Dis_StopHere;
break;
}
/* A4: movsb */
case 0xFF: /* Grp5 Ev */
if (haveF2orF3(pfx)) goto decode_failure;
- delta = dis_Grp5 ( pfx, sz, delta, &whatNext );
+ delta = dis_Grp5 ( pfx, sz, delta, &dres );
break;
/* ------------------------ Escapes to 2-byte opcodes -- */
case 0x8E: /* JLEb/JNGb (jump less or equal) */
case 0x8F: /* JGb/JNLEb (jump greater) */
if (haveF2orF3(pfx)) goto decode_failure;
- d64 = (guest_rip_bbstart+delta+4) + getSDisp32(delta);
+ d64 = (guest_RIP_bbstart+delta+4) + getSDisp32(delta);
delta += 4;
jcc_01( (AMD64Condcode)(opc - 0x80),
- guest_rip_bbstart+delta,
+ guest_RIP_bbstart+delta,
d64 );
- whatNext = Dis_StopHere;
+ dres.whatNext = Dis_StopHere;
DIP("j%s-32 0x%llx\n", name_AMD64Condcode(opc - 0x80), d64);
break;
/* =-=-=-=-=-=-=-=-=- SYSCALL -=-=-=-=-=-=-=-=-=-= */
case 0x05: /* SYSCALL */
- guest_rip_next_mustcheck = True;
- guest_rip_next_assumed = guest_rip_bbstart + delta;
- putIReg64( R_RCX, mkU64(guest_rip_next_assumed) );
+ guest_RIP_next_mustcheck = True;
+ guest_RIP_next_assumed = guest_RIP_bbstart + delta;
+ putIReg64( R_RCX, mkU64(guest_RIP_next_assumed) );
/* It's important that all guest state is up-to-date
at this point. So we declare an end-of-block here, which
forces any cached guest state to be flushed. */
- jmp_lit(Ijk_Syscall, guest_rip_next_assumed);
- whatNext = Dis_StopHere;
+ jmp_lit(Ijk_Syscall, guest_RIP_next_assumed);
+ dres.whatNext = Dis_StopHere;
DIP("syscall\n");
break;
RIP should be up-to-date since it made so at the start of each
insn, but nevertheless be paranoid and update it again right
now. */
- stmt( IRStmt_Put( OFFB_RIP, mkU64(guest_rip_curr_instr) ) );
- jmp_lit(Ijk_NoDecode, guest_rip_curr_instr);
- whatNext = Dis_StopHere;
- *size = 0;
- return whatNext;
+ stmt( IRStmt_Put( OFFB_RIP, mkU64(guest_RIP_curr_instr) ) );
+ jmp_lit(Ijk_NoDecode, guest_RIP_curr_instr);
+ dres.whatNext = Dis_StopHere;
+ dres.len = 0;
+ return dres;
} /* switch (opc) for the main (primary) opcode switch. */
decode_success:
/* All decode successes end up here. */
DIP("\n");
- *size = delta - delta_start;
- return whatNext;
+ dres.len = (Int)toUInt(delta - delta_start);
+ return dres;
}
#undef DIP
#undef DIS
+
+/*------------------------------------------------------------*/
+/*--- Top-level fn ---*/
+/*------------------------------------------------------------*/
+
+/* Disassemble a single instruction into IR. The instruction
+ is located in host memory at &guest_code[delta]. */
+
+DisResult disInstr_AMD64 ( IRBB* irbb_IN,
+ Bool put_IP,
+ Bool (*resteerOkFn) ( Addr64 ),
+ UChar* guest_code_IN,
+ Long delta,
+ Addr64 guest_IP,
+ VexArchInfo* archinfo,
+ Bool host_bigendian_IN )
+{
+ DisResult dres;
+
+ /* Set globals (see top of this file) */
+ guest_code = guest_code_IN;
+ irbb = irbb_IN;
+ host_is_bigendian = host_bigendian_IN;
+ guest_RIP_curr_instr = guest_IP;
+ guest_RIP_bbstart = guest_IP - delta;
+
+ /* We'll consult these after doing disInstr_AMD64_WRK. */
+ guest_RIP_next_assumed = 0;
+ guest_RIP_next_mustcheck = False;
+
+ dres = disInstr_AMD64_WRK ( put_IP, resteerOkFn,
+ delta, archinfo );
+
+ /* If disInstr_AMD64_WRK tried to figure out the next rip, check it
+ got it right. Failure of this assertion is serious and denotes
+ a bug in disInstr. */
+ if (guest_RIP_next_mustcheck
+ && guest_RIP_next_assumed != guest_RIP_curr_instr + dres.len) {
+ vex_printf("\n");
+ vex_printf("assumed next %%rip = 0x%llx\n",
+ guest_RIP_next_assumed );
+ vex_printf(" actual next %%rip = 0x%llx\n",
+ guest_RIP_curr_instr + dres.len );
+ vpanic("bbToIR_AMD64: disInstr miscalculated next %rip");
+ }
+
+ return dres;
+}
+
+
+
/*--------------------------------------------------------------------*/
/*--- end guest-amd64/toIR.c ---*/
/*--------------------------------------------------------------------*/
--- /dev/null
+
+/*--------------------------------------------------------------------*/
+/*--- ---*/
+/*--- This file (guest-generic/bb_to_IR.c) is ---*/
+/*--- Copyright (c) OpenWorks LLP. All rights reserved. ---*/
+/*--- ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of LibVEX, a library for dynamic binary
+ instrumentation and translation.
+
+ Copyright (C) 2004-2005 OpenWorks LLP.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; Version 2 dated June 1991 of the
+ license.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or liability
+ for damages. See the GNU General Public License for more details.
+
+ Neither the names of the U.S. Department of Energy nor the
+ University of California nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without prior written permission.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+*/
+
+#include "libvex_basictypes.h"
+#include "libvex_ir.h"
+#include "libvex.h"
+#include "main/vex_util.h"
+#include "main/vex_globals.h"
+#include "guest-generic/bb_to_IR.h"
+
+
+/* Disassemble a complete basic block, starting at guest_IP_start,
+ returning a new IRBB. The disassembler may chase across basic
+ block boundaries if it wishes and if chase_into_ok allows it.
+ The precise guest address ranges from which code has been taken
+ are written into vge. guest_IP_start is taken to be the IP in
+ the guest's address space corresponding to the instruction at
+ &guest_code[0].
+
+ dis_instr_fn is the arch-specific fn to disassemble on function; it
+ is this that does the real work.
+*/
+
+static Bool const_False ( Addr64 a ) { return False; }
+
+IRBB* bb_to_IR ( /*OUT*/VexGuestExtents* vge,
+ /*IN*/ DisOneInstrFn dis_instr_fn,
+ /*IN*/ UChar* guest_code,
+ /*IN*/ Addr64 guest_IP_bbstart,
+ /*IN*/ Bool (*chase_into_ok)(Addr64),
+ /*IN*/ Bool host_bigendian,
+ /*IN*/ VexArchInfo* archinfo_guest,
+ /*IN*/ IRType guest_word_type )
+{
+ Long delta;
+ Int i, n_instrs, first_stmt_idx;
+ Bool resteerOK, need_to_put_IP, debug_print;
+ DisResult dres;
+ IRStmt* imark;
+ static Int n_resteers = 0;
+ Int d_resteers = 0;
+ IRBB* irbb;
+ Addr64 guest_IP_curr_instr;
+
+ Bool (*resteerOKfn)(Addr64) = NULL;
+
+ debug_print = toBool(vex_traceflags & VEX_TRACE_FE);
+
+ /* check sanity .. */
+ vassert(vex_control.guest_max_insns >= 1);
+ 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_word_type == Ity_I32 || guest_word_type == Ity_I64);
+
+ /* Start a new, empty extent. */
+ vge->n_used = 1;
+ vge->base[0] = guest_IP_bbstart;
+ vge->len[0] = 0;
+
+ /* And a new IR BB to dump the result into. */
+ irbb = emptyIRBB();
+
+ /* Delta keeps track of how far along the guest_code array we have
+ so far gone. */
+ delta = 0;
+ n_instrs = 0;
+
+ while (True) {
+ vassert(n_instrs < vex_control.guest_max_insns);
+
+ /* Regardless of what chase_into_ok says, is chasing permissible
+ at all right now? Set resteerOKfn accordingly. */
+ resteerOK
+ = toBool(
+ 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
+ );
+
+ resteerOKfn
+ = resteerOK ? chase_into_ok : const_False;
+
+ /* This is the IP of the instruction we're just about to deal
+ with. */
+ guest_IP_curr_instr = guest_IP_bbstart + delta;
+
+ /* This is the irbb statement array index of the first stmt in
+ this insn. That will always be the instruction-mark
+ descriptor. */
+ first_stmt_idx = irbb->stmts_used;
+
+ /* Add an instruction-mark statement. We won't know until after
+ disassembling the instruction how long it instruction is, so
+ just put in a zero length and we'll fix it up later. */
+ addStmtToIRBB( irbb, IRStmt_IMark( guest_IP_curr_instr, 0 ));
+
+ /* for the first insn, the dispatch loop will have set
+ %IP, but for all the others we have to do it ourselves. */
+ need_to_put_IP = toBool(n_instrs > 0);
+
+ /* Finally, actually disassemble an instruction. */
+ dres = dis_instr_fn ( irbb,
+ need_to_put_IP,
+ resteerOKfn,
+ guest_code,
+ delta,
+ guest_IP_curr_instr,
+ archinfo_guest,
+ host_bigendian );
+
+ /* stay sane ... */
+ vassert(dres.whatNext == Dis_StopHere
+ || dres.whatNext == Dis_Continue
+ || dres.whatNext == Dis_Resteer);
+ vassert(dres.len >= 0 && dres.len <= 18);
+ if (dres.whatNext != Dis_Resteer)
+ vassert(dres.continueAt == 0);
+
+ /* Fill in the insn-mark length field. */
+ vassert(first_stmt_idx >= 0 && first_stmt_idx < irbb->stmts_used);
+ imark = irbb->stmts[first_stmt_idx];
+ vassert(imark);
+ vassert(imark->tag == Ist_IMark);
+ vassert(imark->Ist.IMark.len == 0);
+ imark->Ist.IMark.len = toUInt(dres.len);
+
+ /* Print the resulting IR, if needed. */
+ if (vex_traceflags & VEX_TRACE_FE) {
+ for (i = first_stmt_idx; i < irbb->stmts_used; i++) {
+ vex_printf(" ");
+ ppIRStmt(irbb->stmts[i]);
+ vex_printf("\n");
+ }
+ }
+
+ /* If dis_instr_fn terminated the BB at this point, check it
+ also filled in the irbb->next field. */
+ if (dres.whatNext == Dis_StopHere) {
+ vassert(irbb->next != NULL);
+ if (debug_print) {
+ vex_printf(" ");
+ vex_printf( "goto {");
+ ppIRJumpKind(irbb->jumpkind);
+ vex_printf( "} ");
+ ppIRExpr( irbb->next );
+ vex_printf( "\n");
+ }
+ }
+
+ /* Update the VexGuestExtents we are constructing. */
+ /* If vex_control.guest_max_insns is required to be < 500 and
+ each insn is at max 15 bytes long, this limit of 10000 then
+ seems reasonable since the max possible extent length will be
+ 500 * 15 == 7500. */
+ vassert(vge->len[vge->n_used-1] < 10000);
+ vge->len[vge->n_used-1]
+ = toUShort(toUInt( vge->len[vge->n_used-1] + dres.len ));
+ n_instrs++;
+ if (debug_print)
+ vex_printf("\n");
+
+ /* Advance delta (inconspicuous but very important :-) */
+ delta += (Long)dres.len;
+
+ switch (dres.whatNext) {
+ case Dis_Continue:
+ vassert(irbb->next == NULL);
+ if (n_instrs < vex_control.guest_max_insns) {
+ /* keep going */
+ } else {
+ /* We have to stop. */
+ irbb->next
+ = IRExpr_Const(
+ guest_word_type == Ity_I32
+ ? IRConst_U32(toUInt(guest_IP_bbstart+delta))
+ : IRConst_U64(guest_IP_bbstart+delta)
+ );
+ return irbb;
+ }
+ break;
+ case Dis_StopHere:
+ vassert(irbb->next != NULL);
+ return irbb;
+ case Dis_Resteer:
+ /* Check that we actually allowed a resteer .. */
+ vassert(resteerOK);
+ vassert(irbb->next == NULL);
+ /* figure out a new delta to continue at. */
+ vassert(resteerOKfn(dres.continueAt));
+ delta = dres.continueAt - guest_IP_bbstart;
+ /* we now have to start a new extent slot. */
+ vge->n_used++;
+ vassert(vge->n_used <= 3);
+ vge->base[vge->n_used-1] = dres.continueAt;
+ vge->len[vge->n_used-1] = 0;
+ n_resteers++;
+ d_resteers++;
+ if (0 && (n_resteers & 0xFF) == 0)
+ vex_printf("resteer[%d,%d] to 0x%llx (delta = %lld)\n",
+ n_resteers, d_resteers,
+ dres.continueAt, delta);
+ break;
+ default:
+ vpanic("bb_to_IR");
+ }
+ }
+}
+
+
+
+/*--------------------------------------------------------------------*/
+/*--- end guest-generic/bb_to_IR.c ---*/
+/*--------------------------------------------------------------------*/
--- /dev/null
+
+/*--------------------------------------------------------------------*/
+/*--- ---*/
+/*--- This file (guest-generic/bb_to_IR.h) is ---*/
+/*--- Copyright (c) OpenWorks LLP. All rights reserved. ---*/
+/*--- ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of LibVEX, a library for dynamic binary
+ instrumentation and translation.
+
+ Copyright (C) 2004-2005 OpenWorks LLP.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; Version 2 dated June 1991 of the
+ license.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or liability
+ for damages. See the GNU General Public License for more details.
+
+ Neither the names of the U.S. Department of Energy nor the
+ University of California nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without prior written permission.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ USA.
+*/
+
+#ifndef __LIBVEX_GENERIC_BB_TO_IR_H
+#define __LIBVEX_GENERIC_BB_TO_IR_H
+
+
+/* This defines stuff needed by the guest insn disassemblers.
+ It's a bit circular; is imported by
+ - the guest-specific toIR.c files (guest-{x86,amd64,ppc32,arm}/toIR.c)
+ - the generic disassembly driver (bb_to_IR.c)
+ - vex_main.c
+*/
+
+
+/* ---------------------------------------------------------------
+ Result of disassembling an instruction
+ --------------------------------------------------------------- */
+
+/* The results of disassembling an instruction. There are three
+ possible outcomes. For Dis_Resteer, the disassembler _must_
+ continue at the specified address. For Dis_StopHere, the
+ disassembler _must_ terminate the BB. For Dis_Continue, we may at
+ our option either disassemble the next insn, or terminate the BB;
+ but in the latter case we must set the bb's ->next field to point
+ to the next instruction. */
+
+typedef
+
+ struct {
+
+ /* The disassembled insn has this length. Must always be
+ set. */
+ Int len;
+
+ /* What happens next?
+ Dis_StopHere: this insn terminates the BB; we must stop.
+ Dis_Continue: we can optionally continue into the next insn
+ Dis_Resteer: followed a branch; continue at the spec'd addr
+ */
+ enum { Dis_StopHere, Dis_Continue, Dis_Resteer } whatNext;
+
+ /* For Dis_Resteer, this is the guest address we should continue
+ at. Otherwise ignored (should be zero). */
+ Addr64 continueAt;
+
+ }
+
+ DisResult;
+
+
+/* ---------------------------------------------------------------
+ The type of a function which disassembles one instruction.
+ C's function-type syntax is really astonishing bizarre.
+ --------------------------------------------------------------- */
+
+/* A function of this type (DisOneInstrFn) disassembles an instruction
+ located at host address &guest_code[delta], whose guest IP is
+ guest_IP (this may be entirely unrelated to where the insn is
+ actually located in the host's address space.). The returned
+ DisResult.len field carries its size. If the returned
+ DisResult.whatNext field is Dis_Resteer then DisResult.continueAt
+ should hold the guest IP of the next insn to disassemble.
+
+ disInstr is not permitted to return Dis_Resteer if resteerOkFn,
+ when applied to the address which it wishes to resteer into,
+ returns False.
+
+ The resulting IR is added to the end of irbb.
+*/
+
+typedef
+
+ DisResult (*DisOneInstrFn) (
+
+ /* This is the IRBB to which the resulting IR is to be appended. */
+ /*OUT*/ IRBB* irbb,
+
+ /* Do we need to generate IR to set the guest IP for this insn,
+ or not? */
+ /*IN*/ Bool put_IP,
+
+ /* Return True iff resteering to the given addr is allowed */
+ /*IN*/ Bool (*resteerOkFn) ( Addr64 ),
+
+ /* Where is the guest code? */
+ /*IN*/ UChar* guest_code,
+
+ /* Where is the actual insn? Note: it's at &guest_code[delta] */
+ /*IN*/ Long delta,
+
+ /* What is the guest IP of the insn? */
+ /*IN*/ Addr64 guest_IP,
+
+ /* Info about the guest architecture */
+ /*IN*/ VexArchInfo* archinfo,
+
+ /* Is the host bigendian? */
+ /*IN*/ Bool host_bigendian
+
+ );
+
+
+/* ---------------------------------------------------------------
+ Top-level BB to IR conversion fn.
+ --------------------------------------------------------------- */
+
+/* See detailed comment in bb_to_IR.c. */
+extern
+IRBB* bb_to_IR ( /*OUT*/VexGuestExtents* vge,
+ /*IN*/ DisOneInstrFn dis_instr_fn,
+ /*IN*/ UChar* guest_code,
+ /*IN*/ Addr64 guest_IP_bbstart,
+ /*IN*/ Bool (*chase_into_ok)(Addr64),
+ /*IN*/ Bool host_bigendian,
+ /*IN*/ VexArchInfo* archinfo_guest,
+ /*IN*/ IRType guest_word_type );
+
+
+#endif /* ndef GENERIC_BB_TO_IR_H */
+
+/*--------------------------------------------------------------------*/
+/*--- end guest-generic/bb_to_IR.h ---*/
+/*--------------------------------------------------------------------*/
#ifndef __LIBVEX_GUEST_PPC32_DEFS_H
#define __LIBVEX_GUEST_PPC32_DEFS_H
-/* FP Rounding mode - different encoding to IR */
-typedef
- enum {
- PPC32rm_NEAREST = 0,
- PPC32rm_NegINF = 1,
- PPC32rm_PosINF = 2,
- PPC32rm_ZERO = 3
- } PPC32RoundingMode;
-
-/* Floating point comparison values - different encoding to IR */
-typedef
- enum {
- PPC32cr_LT = 0x8,
- PPC32cr_GT = 0x4,
- PPC32cr_EQ = 0x2,
- PPC32cr_UN = 0x1
- }
- PPC32CmpF64Result;
/*---------------------------------------------------------*/
/*--- ppc32 to IR conversion ---*/
/*---------------------------------------------------------*/
+/* Convert one ppc32 insn to IR. See the type DisOneInstrFn in
+ bb_to_IR.h. */
extern
-IRBB* bbToIR_PPC32 ( UChar* ppc32code,
- Addr64 eip,
- VexGuestExtents* vge,
- Bool (*byte_accessible)(Addr64),
- Bool (*resteerOkFn)(Addr64),
- Bool host_bigendian,
- VexArchInfo* archinfo_guest );
+DisResult disInstr_PPC32 ( IRBB* irbb,
+ Bool put_IP,
+ Bool (*resteerOkFn) ( Addr64 ),
+ UChar* guest_code,
+ Long delta,
+ Addr64 guest_IP,
+ VexArchInfo* archinfo,
+ Bool host_bigendian );
/* Used by the optimiser to specialise calls to helpers. */
extern
VexGuestLayout ppc32Guest_layout;
+/* FP Rounding mode - different encoding to IR */
+typedef
+ enum {
+ PPC32rm_NEAREST = 0,
+ PPC32rm_NegINF = 1,
+ PPC32rm_PosINF = 2,
+ PPC32rm_ZERO = 3
+ } PPC32RoundingMode;
+
+/* Floating point comparison values - different encoding to IR */
+typedef
+ enum {
+ PPC32cr_LT = 0x8,
+ PPC32cr_GT = 0x4,
+ PPC32cr_EQ = 0x2,
+ PPC32cr_UN = 0x1
+ }
+ PPC32CmpF64Result;
+
+
/*---------------------------------------------------------*/
/*--- ppc32 guest helpers ---*/
/*---------------------------------------------------------*/
#include "libvex.h"
#include "main/vex_util.h"
+#include "guest-generic/bb_to_IR.h"
#include "guest-ppc32/gdefs.h"
#include "main/vex_util.h"
#include "main/vex_globals.h"
+#include "guest-generic/bb_to_IR.h"
#include "guest-ppc32/gdefs.h"
/*--- Globals ---*/
/*------------------------------------------------------------*/
-/* These are set at the start of the translation of a BB, so that we
- don't have to pass them around endlessly. CONST means does not
- change during translation of a bb.
-*/
+/* These are set at the start of the translation of an insn, right
+ down in disInstr_PPC32, so that we don't have to pass them around
+ endlessly. They are all constant during the translation of any
+ given insn. */
/* We need to know this to do sub-register accesses correctly. */
-/* CONST */
static Bool host_is_bigendian;
/* Pointer to the guest code area. */
-/* CONST */
static UChar* guest_code;
/* The guest address corresponding to guest_code[0]. */
-/* CONST */
-static Addr32 guest_pc_bbstart;
+static Addr32 guest_CIA_bbstart;
/* The guest address for the instruction currently being
translated. */
-/* CONST for any specific insn, not for the entire BB */
-static Addr32 guest_cia_curr_instr;
+static Addr32 guest_CIA_curr_instr;
/* The IRBB* into which we're generating code. */
static IRBB* irbb;
#endif
-
-/*------------------------------------------------------------*/
-/*--- Disassemble an entire basic block ---*/
-/*------------------------------------------------------------*/
-
-/* The results of disassembling an instruction. There are three
- possible outcomes. For Dis_Resteer, the disassembler _must_
- continue at the specified address. For Dis_StopHere, the
- disassembler _must_ terminate the BB. For Dis_Continue, we may at
- our option either disassemble the next insn, or terminate the BB;
- but in the latter case we must set the bb's ->next field to point
- to the next instruction. */
-
-typedef
- enum {
- Dis_StopHere, /* this insn terminates the BB; we must stop. */
- Dis_Continue, /* we can optionally continue into the next insn */
- Dis_Resteer /* followed a branch; continue at the spec'd addr */
- }
- DisResult;
-
-
-/* forward decls .. */
-static IRExpr* mkU32 ( UInt i );
-static void stmt ( IRStmt* st );
-
-
-/* disInstr disassembles an instruction located at &guest_code[delta],
- and sets *size to its size. If the returned value is Dis_Resteer,
- the next guest address is assigned to *whereNext. disInstr is not
- permitted to return Dis_Resteer if either (1) resteerOK is False,
- or (2) resteerOkFn, when applied to the address which it wishes to
- resteer into, returns False. */
-
-static DisResult disInstr ( /*IN*/ Bool resteerOK,
- /*IN*/ Bool (*resteerOkFn) ( Addr64 ),
- /*IN*/ UInt delta,
- /*IN*/ VexArchInfo* archinfo,
- /*OUT*/ Int* size,
- /*OUT*/ Addr64* whereNext );
-
-
-/* This is the main (only, in fact) entry point for this module. */
-
-/* Disassemble a complete basic block, starting at guest_pc_start, and
- dumping the IR into global irbb. Returns the size, in bytes, of
- the basic block.
-*/
-IRBB* bbToIR_PPC32 ( UChar* ppc32code,
- Addr64 guest_pc_start,
- VexGuestExtents* vge,
- Bool (*byte_accessible)(Addr64),
- Bool (*chase_into_ok)(Addr64),
- Bool host_bigendian,
- VexArchInfo* archinfo_guest )
-{
- UInt delta;
- Int i, n_instrs, size, first_stmt_idx;
- Addr64 guest_next;
- Bool resteerOK;
- DisResult dres;
- static Int n_resteers = 0;
- Int d_resteers = 0;
-
- /* check sanity .. */
- vassert(vex_control.guest_max_insns >= 1);
- vassert(vex_control.guest_max_insns < 1000);
- vassert(vex_control.guest_chase_thresh >= 0);
- vassert(vex_control.guest_chase_thresh < vex_control.guest_max_insns);
-
- vassert(archinfo_guest->subarch == VexSubArchPPC32_noAV
- || archinfo_guest->subarch == VexSubArchPPC32_AV);
-
- /* 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 = ppc32code;
- guest_pc_bbstart = (Addr32)guest_pc_start;
- irbb = emptyIRBB();
-
- vassert((guest_pc_start >> 32) == 0);
-
- /* Delta keeps track of how far along the ppc32code array we
- have so far gone. */
- delta = 0;
- n_instrs = 0;
-
- while (True) {
- vassert(n_instrs < vex_control.guest_max_insns);
-
- guest_next = 0;
- resteerOK = toBool(n_instrs < vex_control.guest_chase_thresh);
- first_stmt_idx = irbb->stmts_used;
-
- guest_cia_curr_instr = guest_pc_bbstart + delta;
-
- if (n_instrs > 0) {
- /* for the first insn, the dispatch loop will have set
- CIA, but for all the others we have to do it ourselves. */
- putReg( PPC32_SPR_CIA, mkU32(guest_cia_curr_instr) );
- }
-
- dres = disInstr( resteerOK, chase_into_ok,
- delta, archinfo_guest, &size, &guest_next );
-
- /* Print the resulting IR, if needed. */
- if (vex_traceflags & VEX_TRACE_FE) {
- for (i = first_stmt_idx; i < irbb->stmts_used; i++) {
- vex_printf(" ");
- ppIRStmt(irbb->stmts[i]);
- vex_printf("\n");
- }
- }
-
- if (dres == Dis_StopHere) {
- vassert(irbb->next != NULL);
- if (vex_traceflags & VEX_TRACE_FE) {
- vex_printf(" ");
- vex_printf( "goto {");
- ppIRJumpKind(irbb->jumpkind);
- vex_printf( "} ");
- ppIRExpr( irbb->next );
- vex_printf( "\n");
- }
- }
-
- delta += size;
- vge->len[vge->n_used-1] += size;
- n_instrs++;
- DIP("\n");
-
- vassert(size == 0 || size == 4);
- if (!resteerOK)
- vassert(dres != Dis_Resteer);
- if (dres != Dis_Resteer)
- vassert(guest_next == 0);
-
- switch (dres) {
- case Dis_Continue:
- vassert(irbb->next == NULL);
- if (n_instrs < vex_control.guest_max_insns) {
- /* keep going */
- } else {
- irbb->next = mkU32(((Addr32)guest_pc_start)+delta);
- return irbb;
- }
- break;
- case Dis_StopHere:
- vassert(irbb->next != NULL);
- return irbb;
- case Dis_Resteer:
- vassert(irbb->next == NULL);
- /* figure out a new delta to continue at. */
- vassert(chase_into_ok(guest_next));
- delta = (UInt)(guest_next - guest_pc_start);
- n_resteers++;
- d_resteers++;
- if (0 && (n_resteers & 0xFF) == 0)
- vex_printf("resteer[%d,%d] to %p (delta = %d)\n",
- n_resteers, d_resteers,
- ULong_to_Ptr(guest_next), (Int)delta);
- break;
-
- default: vpanic("bbToIR_PPC32(ppc32)");
- }
- }
-}
-
-
/*------------------------------------------------------------*/
/*--- Helper bits and pieces for deconstructing the ---*/
/*--- ppc32 insn stream. ---*/
{
vassert(archreg < 32);
-// vassert(!host_is_bigendian);
// jrs: probably not necessary; only matters if we reference sub-parts
// of the ppc32 registers, but that isn't the case
+ // later: this might affect Altivec though?
+ vassert(host_is_bigendian);
switch (archreg) {
case 0: return offsetof(VexGuestPPC32State, guest_GPR0);
IRStmt_Exit(
binop(Iop_CmpNE32, mkU32(ew), mkU32(EmWarn_NONE)),
Ijk_EmWarn,
- IRConst_U32(guest_cia_curr_instr + 4)
+ IRConst_U32(guest_CIA_curr_instr + 4)
)
);
}
/*
Integer Branch Instructions
*/
-static Bool dis_branch ( UInt theInstr, DisResult *whatNext )
+static Bool dis_branch ( UInt theInstr, DisResult* dres )
{
UChar opc1 = toUChar((theInstr >> 26) & 0x3F); /* theInstr[26:31] */
UChar BO = toUChar((theInstr >> 21) & 0x1F); /* theInstr[21:25] */
/* Hack to pass through code that just wants to read the PC */
if (theInstr == 0x429F0005) {
DIP("bcl 0x%x, 0x%x,\n", BO, BI);
- putReg( PPC32_SPR_LR, mkU32(guest_cia_curr_instr + 4) );
+ putReg( PPC32_SPR_LR, mkU32(guest_CIA_curr_instr + 4) );
return True;
}
if (flag_AA) {
nia = (UInt)exts_LI;
} else {
- nia = (UInt)((Int)guest_cia_curr_instr + exts_LI);
+ nia = (UInt)((Int)guest_CIA_curr_instr + exts_LI);
}
DIP("b%s%s 0x%x\n", flag_LK ? "l" : "", flag_AA ? "a" : "", nia);
if (flag_LK) {
- putReg( PPC32_SPR_LR, mkU32(guest_cia_curr_instr+4) );
+ putReg( PPC32_SPR_LR, mkU32(guest_CIA_curr_instr+4) );
}
irbb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
irbb->next = mkU32(nia);
if (flag_AA) {
nia = (UInt)exts_BD;
} else {
- nia = (UInt)((Int)guest_cia_curr_instr + exts_BD);
+ nia = (UInt)((Int)guest_CIA_curr_instr + exts_BD);
}
if (flag_LK) {
assign( lr, IRExpr_Mux0X( unop(Iop_32to8, mkexpr(do_branch)),
getReg( PPC32_SPR_LR ),
- mkU32(guest_cia_curr_instr + 4)));
+ mkU32(guest_CIA_curr_instr + 4)));
putReg( PPC32_SPR_LR, mkexpr(lr) );
}
IRConst_U32(nia) ));
irbb->jumpkind = Ijk_Boring;
- irbb->next = mkU32(guest_cia_curr_instr + 4);
+ irbb->next = mkU32(guest_CIA_curr_instr + 4);
break;
case 0x13:
if (flag_LK) {
assign( lr, IRExpr_Mux0X( unop(Iop_1Uto8, mkexpr(cond_ok)),
getReg( PPC32_SPR_LR ),
- mkU32(guest_cia_curr_instr + 4)));
+ mkU32(guest_CIA_curr_instr + 4)));
putReg( PPC32_SPR_LR, mkexpr(lr) );
}
stmt( IRStmt_Exit( unop(Iop_Not1, mkexpr(cond_ok)),
Ijk_Boring,
- IRConst_U32(guest_cia_curr_instr + 4) ));
+ IRConst_U32(guest_CIA_curr_instr + 4) ));
irbb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
irbb->next = mkexpr(ir_nia);
if (flag_LK) {
assign( lr, IRExpr_Mux0X( unop(Iop_32to8, mkexpr(do_branch)),
getReg( PPC32_SPR_LR ),
- mkU32(guest_cia_curr_instr + 4)) );
+ mkU32(guest_CIA_curr_instr + 4)) );
putReg( PPC32_SPR_LR, mkexpr(lr) );
}
stmt( IRStmt_Exit( unop(Iop_Not1, unop(Iop_32to1, mkexpr(do_branch))),
Ijk_Boring,
- IRConst_U32(guest_cia_curr_instr + 4) ));
+ IRConst_U32(guest_CIA_curr_instr + 4) ));
irbb->jumpkind = flag_LK ? Ijk_Call : Ijk_Boring;
irbb->next = mkexpr(ir_nia);
return False;
}
- *whatNext = Dis_StopHere;
+ dres->whatNext = Dis_StopHere;
return True;
}
/*
System Linkage Instructions
*/
-static Bool dis_syslink ( UInt theInstr, DisResult *whatNext )
+static Bool dis_syslink ( UInt theInstr, DisResult* dres )
{
if (theInstr != 0x44000002) {
vex_printf("dis_int_syslink(PPC32)(theInstr)\n");
/* It's important that all ArchRegs carry their up-to-date value
at this point. So we declare an end-of-block here, which
forces any TempRegs caching ArchRegs to be flushed. */
- irbb->next = mkU32( guest_cia_curr_instr + 4 );
+ irbb->next = mkU32( guest_CIA_curr_instr + 4 );
irbb->jumpkind = Ijk_Syscall;
- *whatNext = Dis_StopHere;
+ dres->whatNext = Dis_StopHere;
return True;
}
Cache Management Instructions
*/
static Bool dis_cache_manage ( UInt theInstr,
- DisResult* whatNext,
+ DisResult* dres,
VexArchInfo* guest_archinfo )
{
/* X-Form */
stmt( IRStmt_MFence() );
irbb->jumpkind = Ijk_TInval;
- irbb->next = mkU32(guest_cia_curr_instr + 4);
- *whatNext = Dis_StopHere;
+ irbb->next = mkU32(guest_CIA_curr_instr + 4);
+ dres->whatNext = Dis_StopHere;
break;
}
/*------------------------------------------------------------*/
/* Disassemble a single instruction into IR. The instruction
- is located in host memory at &guest_code[delta].
- Set *size to be the size of the instruction.
- If the returned value is Dis_Resteer,
- the next guest address is assigned to *whereNext. If resteerOK
- is False, disInstr may not return Dis_Resteer. */
-
-static DisResult disInstr ( /*IN*/ Bool resteerOK,
- /*IN*/ Bool (*resteerOkFn) ( Addr64 ),
- /*IN*/ UInt delta,
- /*IN*/ VexArchInfo* archinfo,
- /*OUT*/ Int* size,
- /*OUT*/ Addr64* whereNext )
+ is located in host memory at &guest_code[delta]. */
+
+static
+DisResult disInstr_PPC32_WRK (
+ Bool put_IP,
+ Bool (*resteerOkFn) ( Addr64 ),
+ Long delta64,
+ VexArchInfo* archinfo
+ )
{
- UChar opc1;
- UInt opc2;
- DisResult whatNext = Dis_Continue;
+ UChar opc1;
+ UInt opc2;
+ DisResult dres;
UInt theInstr;
+ /* The running delta */
+ Int delta = (Int)delta64;
+
+ /* Set result defaults. */
+ dres.whatNext = Dis_Continue;
+ dres.len = 0;
+ dres.continueAt = 0;
/* At least this is simple on PPC32: insns are all 4 bytes long, and
4-aligned. So just fish the whole thing out of memory right now
and have done. */
-
- /* We will set *size to 4 if the insn is successfully decoded.
- Setting it to 0 by default makes bbToIR_PPC32 abort if we fail the
- decode. */
- *size = 0;
-
theInstr = getUIntBigendianly( (UChar*)(&guest_code[delta]) );
- DIP("\t0x%x: ", guest_pc_bbstart+delta);
-
+ DIP("\t0x%x: ", guest_CIA_bbstart+delta);
/* Spot the client-request magic sequence. */
// Essentially a v. unlikely sequence of noops that we can catch
code[4] == 0x54009800 &&
code[5] == 0x60000000) {
DIP("%%r3 = client_request ( %%r31 )\n");
- *size = 24;
+ dres.len = 24;
delta += 24;
- irbb->next = mkU32(guest_pc_bbstart+delta);
+ irbb->next = mkU32(guest_CIA_bbstart+delta);
irbb->jumpkind = Ijk_ClientReq;
- whatNext = Dis_StopHere;
+ dres.whatNext = Dis_StopHere;
goto decode_success;
}
}
/* Branch Instructions */
case 0x12: case 0x10: // b, bc
- if (dis_branch(theInstr, &whatNext)) goto decode_success;
+ if (dis_branch(theInstr, &dres)) goto decode_success;
goto decode_failure;
/* System Linkage Instructions */
case 0x11: // sc
- if (dis_syslink(theInstr, &whatNext)) goto decode_success;
+ if (dis_syslink(theInstr, &dres)) goto decode_success;
goto decode_failure;
/* Trap Instructions */
/* Branch Instructions */
case 0x210: case 0x010: // bcctr, bclr
- if (dis_branch(theInstr, &whatNext)) goto decode_success;
+ if (dis_branch(theInstr, &dres)) goto decode_success;
goto decode_failure;
/* Memory Synchronization Instructions */
case 0x2F6: case 0x056: case 0x036: // dcba, dcbf, dcbst
case 0x116: case 0x0F6: case 0x3F6: // dcbt, dcbtst, dcbz
case 0x3D6: // icbi
- if (dis_cache_manage( theInstr, &whatNext, archinfo ))
+ if (dis_cache_manage( theInstr, &dres, archinfo ))
goto decode_success;
goto decode_failure;
CIA should be up-to-date since it made so at the start of each
insn, but nevertheless be paranoid and update it again right
now. */
- putReg( PPC32_SPR_CIA, mkU32(guest_cia_curr_instr) );
- irbb->next = mkU32(guest_cia_curr_instr);
+ putReg( PPC32_SPR_CIA, mkU32(guest_CIA_curr_instr) );
+ irbb->next = mkU32(guest_CIA_curr_instr);
irbb->jumpkind = Ijk_NoDecode;
- whatNext = Dis_StopHere;
- *size = 0;
- return whatNext;
+ dres.whatNext = Dis_StopHere;
+ dres.len = 0;
+ return dres;
} /* switch (opc) for the main (primary) opcode switch. */
decode_success:
/* All decode successes end up here. */
-// vex_printf("disInstr(ppc32): success");
DIP("\n");
- *size = 4;
- return whatNext;
+ dres.len = 4;
+ return dres;
}
#undef DIP
#undef DIS
+
+/*------------------------------------------------------------*/
+/*--- Top-level fn ---*/
+/*------------------------------------------------------------*/
+
+/* Disassemble a single instruction into IR. The instruction
+ is located in host memory at &guest_code[delta]. */
+
+DisResult disInstr_PPC32 ( IRBB* irbb_IN,
+ Bool put_IP,
+ Bool (*resteerOkFn) ( Addr64 ),
+ UChar* guest_code_IN,
+ Long delta,
+ Addr64 guest_IP,
+ VexArchInfo* archinfo,
+ Bool host_bigendian_IN )
+{
+ DisResult dres;
+
+ /* Set globals (see top of this file) */
+ guest_code = guest_code_IN;
+ irbb = irbb_IN;
+ host_is_bigendian = host_bigendian_IN;
+ guest_CIA_curr_instr = (Addr32)guest_IP;
+ guest_CIA_bbstart = (Addr32)toUInt(guest_IP - delta);
+
+ dres = disInstr_PPC32_WRK ( put_IP, resteerOkFn,
+ delta, archinfo );
+
+ return dres;
+}
+
+
/*--------------------------------------------------------------------*/
/*--- end guest-ppc32/toIR.c ---*/
/*--------------------------------------------------------------------*/
/*--- x86 to IR conversion ---*/
/*---------------------------------------------------------*/
+/* Convert one x86 insn to IR. See the type DisOneInstrFn in
+ bb_to_IR.h. */
extern
-IRBB* bbToIR_X86 ( UChar* x86code,
- Addr64 eip,
- VexGuestExtents* vge,
- Bool (*byte_accessible)(Addr64),
- Bool (*resteerOkFn)(Addr64),
- Bool host_bigendian,
- VexArchInfo* archinfo_guest );
+DisResult disInstr_X86 ( IRBB* irbb,
+ Bool put_IP,
+ Bool (*resteerOkFn) ( Addr64 ),
+ UChar* guest_code,
+ Long delta,
+ Addr64 guest_IP,
+ VexArchInfo* archinfo,
+ Bool host_bigendian );
/* Used by the optimiser to specialise calls to helpers. */
extern
#include "libvex.h"
#include "main/vex_util.h"
+#include "guest-generic/bb_to_IR.h"
#include "guest-x86/gdefs.h"
#include "guest-generic/g_generic_x87.h"
#include "main/vex_util.h"
#include "main/vex_globals.h"
+#include "guest-generic/bb_to_IR.h"
#include "guest-x86/gdefs.h"
/*--- Globals ---*/
/*------------------------------------------------------------*/
-/* These are set at the start of the translation of a BB, so
- that we don't have to pass them around endlessly. */
+/* These are set at the start of the translation of an insn, right
+ down in disInstr_X86, so that we don't have to pass them around
+ endlessly. They are all constant during the translation of any
+ given insn. */
/* We need to know this to do sub-register accesses correctly. */
-/* CONST */
static Bool host_is_bigendian;
-/* Pointer to the guest code area. */
-/* CONST */
+/* Pointer to the guest code area (points to start of BB, not to the
+ insn being processed). */
static UChar* guest_code;
/* The guest address corresponding to guest_code[0]. */
-/* CONST */
-static Addr32 guest_eip_bbstart;
+static Addr32 guest_EIP_bbstart;
/* The guest address for the instruction currently being
translated. */
-/* CONST for any specific insn, not for the entire BB */
-static Addr32 guest_eip_curr_instr;
+static Addr32 guest_EIP_curr_instr;
/* The IRBB* into which we're generating code. */
static IRBB* irbb;
-/* Emergency verboseness just for this insn? DEBUG ONLY */
-static Bool insn_verbose = False;
-
/*------------------------------------------------------------*/
/*--- Debugging output ---*/
/*------------------------------------------------------------*/
#define DIP(format, args...) \
- if (insn_verbose || (vex_traceflags & VEX_TRACE_FE)) \
+ if (vex_traceflags & VEX_TRACE_FE) \
vex_printf(format, ## args)
#define DIS(buf, format, args...) \
- if (insn_verbose || (vex_traceflags & VEX_TRACE_FE)) \
+ if (vex_traceflags & VEX_TRACE_FE) \
vex_sprintf(buf, format, ## args)
#define OFFB_EMWARN offsetof(VexGuestX86State,guest_EMWARN)
-/*------------------------------------------------------------*/
-/*--- Disassemble an entire basic block ---*/
-/*------------------------------------------------------------*/
-
-/* The results of disassembling an instruction. There are three
- possible outcomes. For Dis_Resteer, the disassembler _must_
- continue at the specified address. For Dis_StopHere, the
- disassembler _must_ terminate the BB. For Dis_Continue, we may at
- our option either disassemble the next insn, or terminate the BB;
- but in the latter case we must set the bb's ->next field to point
- to the next instruction. */
-
-typedef
- enum {
- Dis_StopHere, /* this insn terminates the BB; we must stop. */
- Dis_Continue, /* we can optionally continue into the next insn */
- Dis_Resteer /* followed a branch; continue at the spec'd addr */
- }
- DisResult;
-
-
-/* forward decls .. */
-static IRExpr* mkU32 ( UInt i );
-static void stmt ( IRStmt* st );
-
-
-/* disInstr disassembles an instruction located at &guest_code[delta],
- and sets *size to its size. If the returned value is Dis_Resteer,
- the next guest address is assigned to *whereNext. disInstr is not
- permitted to return Dis_Resteer if either (1) resteerOK is False,
- or (2) resteerOkFn, when applied to the address which it wishes to
- resteer into, returns False. */
-
-static
-DisResult disInstr ( /*IN*/ Bool resteerOK,
- /*IN*/ Bool (*resteerOkFn) ( Addr64 ),
- /*IN*/ UInt delta,
- /*IN*/ VexArchInfo* archinfo,
- /*OUT*/ Int* size,
- /*OUT*/ Addr64* whereNext );
-
-
-/* This is the main (only, in fact) entry point for this module. */
-
-/* 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,
- VexGuestExtents* vge,
- Bool (*byte_accessible)(Addr64),
- Bool (*chase_into_ok)(Addr64),
- Bool host_bigendian,
- VexArchInfo* archinfo_guest )
-{
- UInt delta;
- Int i, n_instrs, size, first_stmt_idx;
- Addr64 guest_next;
- Bool resteerOK;
- DisResult dres;
- IRStmt* imark;
- static Int n_resteers = 0;
- Int d_resteers = 0;
-
- /* check sanity .. */
- vassert(vex_control.guest_max_insns >= 1);
- 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(archinfo_guest->subarch == VexSubArchX86_sse0
- || archinfo_guest->subarch == VexSubArchX86_sse1
- || archinfo_guest->subarch == VexSubArchX86_sse2);
-
- 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;
- guest_eip_bbstart = (Addr32)guest_eip_start;
- irbb = emptyIRBB();
- insn_verbose = False;
-
- /* Delta keeps track of how far along the x86code array we
- have so far gone. */
- delta = 0;
- n_instrs = 0;
-
- while (True) {
- vassert(n_instrs < vex_control.guest_max_insns);
-
- guest_next = 0;
- resteerOK
- = toBool(
- 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
- );
-
- /* This is the %EIP of the instruction we're just about to deal
- with. */
- guest_eip_curr_instr = guest_eip_bbstart + delta;
-
- /* This is the irbb statement array index of the first stmt in
- this insn. That will always be the instruction-mark
- descriptor. */
- first_stmt_idx = irbb->stmts_used;
-
- /* Add an instruction-mark statement. We won't know until after
- disInstr how long the instruction is, so just put in a zero
- length and we'll fix it up later. */
- stmt( IRStmt_IMark( (Addr64)guest_eip_curr_instr, 0 ));
-
- if (n_instrs > 0) {
- /* for the first insn, the dispatch loop will have set
- %EIP, but for all the others we have to do it ourselves. */
- stmt( IRStmt_Put( OFFB_EIP, mkU32(guest_eip_curr_instr)) );
- }
-
- /* Do the instruction. This may set insn_verbose to True, which
- needs to be annulled. */
- size = 0; /* just in case disInstr doesn't set it */
- dres = disInstr( resteerOK, chase_into_ok,
- delta, archinfo_guest, &size, &guest_next );
- insn_verbose = False;
-
- /* stay sane ... */
- vassert(size >= 0 && size <= 18);
-
- /* Fill in the insn-mark length field. */
- vassert(first_stmt_idx >= 0 && first_stmt_idx < irbb->stmts_used);
- imark = irbb->stmts[first_stmt_idx];
- vassert(imark);
- vassert(imark->tag == Ist_IMark);
- vassert(imark->Ist.IMark.len == 0);
- imark->Ist.IMark.len = size;
-
- /* Print the resulting IR, if needed. */
- if (vex_traceflags & VEX_TRACE_FE) {
- for (i = first_stmt_idx; i < irbb->stmts_used; i++) {
- vex_printf(" ");
- ppIRStmt(irbb->stmts[i]);
- vex_printf("\n");
- }
- }
-
- if (dres == Dis_StopHere) {
- vassert(irbb->next != NULL);
- if (vex_traceflags & VEX_TRACE_FE) {
- vex_printf(" ");
- vex_printf( "goto {");
- ppIRJumpKind(irbb->jumpkind);
- vex_printf( "} ");
- ppIRExpr( irbb->next );
- vex_printf( "\n");
- }
- }
-
- delta += size;
- /* If vex_control.guest_max_insns is required to be < 500 and
- each insn is at max 15 bytes long, this limit of 10000 then
- seems reasonable since the max possible extent length will be
- 500 * 15 == 7500. */
- vassert(vge->len[vge->n_used-1] < 10000);
- vge->len[vge->n_used-1]
- = toUShort(toUInt( vge->len[vge->n_used-1] + size ));
- n_instrs++;
- DIP("\n");
-
- if (!resteerOK)
- vassert(dres != Dis_Resteer);
- if (dres != Dis_Resteer)
- vassert(guest_next == 0);
-
- switch (dres) {
- case Dis_Continue:
- vassert(irbb->next == NULL);
- if (n_instrs < vex_control.guest_max_insns) {
- /* keep going */
- } else {
- irbb->next = mkU32(((Addr32)guest_eip_start)+delta);
- return irbb;
- }
- break;
- case Dis_StopHere:
- vassert(irbb->next != NULL);
- return irbb;
- case Dis_Resteer:
- vassert(irbb->next == NULL);
- /* figure out a new delta to continue at. */
- vassert(chase_into_ok(guest_next));
- delta = toUInt(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)
- vex_printf("resteer[%d,%d] to %p (delta = %d)\n",
- n_resteers, d_resteers,
- ULong_to_Ptr(guest_next), (Int)delta);
- break;
- }
- }
-}
-
-
/*------------------------------------------------------------*/
/*--- Helper bits and pieces for deconstructing the ---*/
/*--- x86 insn stream. ---*/
IRStmt_Exit(
binop(Iop_CmpNE32, unop(Iop_64HIto32, mkexpr(r64)), mkU32(0)),
Ijk_MapFail,
- IRConst_U32( guest_eip_curr_instr )
+ IRConst_U32( guest_EIP_curr_instr )
)
);
/* Group 5 extended opcodes. */
static
-UInt dis_Grp5 ( UChar sorb, Int sz, UInt delta, DisResult* whatNext )
+UInt dis_Grp5 ( UChar sorb, Int sz, UInt delta, DisResult* dres )
{
Int len;
UChar modrm;
t2 = newTemp(Ity_I32);
assign(t2, binop(Iop_Sub32, getIReg(4,R_ESP), mkU32(4)));
putIReg(4, R_ESP, mkexpr(t2));
- storeLE( mkexpr(t2), mkU32(guest_eip_bbstart+delta+1));
+ storeLE( mkexpr(t2), mkU32(guest_EIP_bbstart+delta+1));
jmp_treg(Ijk_Call,t1);
- *whatNext = Dis_StopHere;
+ dres->whatNext = Dis_StopHere;
break;
case 4: /* jmp Ev */
vassert(sz == 4);
jmp_treg(Ijk_Boring,t1);
- *whatNext = Dis_StopHere;
+ dres->whatNext = Dis_StopHere;
break;
default:
vex_printf(
t2 = newTemp(Ity_I32);
assign(t2, binop(Iop_Sub32, getIReg(4,R_ESP), mkU32(4)));
putIReg(4, R_ESP, mkexpr(t2));
- storeLE( mkexpr(t2), mkU32(guest_eip_bbstart+delta+len));
+ storeLE( mkexpr(t2), mkU32(guest_EIP_bbstart+delta+len));
jmp_treg(Ijk_Call,t1);
- *whatNext = Dis_StopHere;
+ dres->whatNext = Dis_StopHere;
break;
case 4: /* JMP Ev */
vassert(sz == 4);
jmp_treg(Ijk_Boring,t1);
- *whatNext = Dis_StopHere;
+ dres->whatNext = Dis_StopHere;
break;
case 6: /* PUSH Ev */
vassert(sz == 4 || sz == 2);
IRStmt_Exit(
binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
Ijk_EmWarn,
- IRConst_U32( ((Addr32)guest_eip_bbstart)+delta)
+ IRConst_U32( ((Addr32)guest_EIP_bbstart)+delta)
)
);
IRStmt_Exit(
binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
Ijk_EmWarn,
- IRConst_U32( ((Addr32)guest_eip_bbstart)+delta)
+ IRConst_U32( ((Addr32)guest_EIP_bbstart)+delta)
)
);
break;
IRStmt_Exit(
binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
Ijk_EmWarn,
- IRConst_U32( ((Addr32)guest_eip_bbstart)+delta)
+ IRConst_U32( ((Addr32)guest_EIP_bbstart)+delta)
)
);
/*------------------------------------------------------------*/
/* Disassemble a single instruction into IR. The instruction
- is located in host memory at &guest_code[delta].
- Set *size to be the size of the instruction.
- If the returned value is Dis_Resteer,
- the next guest address is assigned to *whereNext. If resteerOK
- is False, disInstr may not return Dis_Resteer. */
-
-static
-DisResult disInstr ( /*IN*/ Bool resteerOK,
- /*IN*/ Bool (*resteerOkFn) ( Addr64 ),
- /*IN*/ UInt delta,
- /*IN*/ VexArchInfo* archinfo,
- /*OUT*/ Int* size,
- /*OUT*/ Addr64* whereNext )
+ is located in host memory at &guest_code[delta]. */
+
+static
+DisResult disInstr_X86_WRK (
+ Bool put_IP,
+ Bool (*resteerOkFn) ( Addr64 ),
+ Long delta64,
+ VexArchInfo* archinfo
+ )
{
IRType ty;
IRTemp addr, t0, t1, t2, t3, t4, t5, t6;
UInt d32;
HChar dis_buf[50];
Int am_sz, d_sz;
- DisResult whatNext = Dis_Continue;
+ DisResult dres;
UChar* insn; /* used in SSE decoders */
+ /* The running delta */
+ Int delta = (Int)delta64;
+
/* Holds eip at the start of the insn, so that we can print
consistent error messages for unimplemented insns. */
- UInt delta_start = delta;
+ Int delta_start = delta;
/* sz denotes the nominal data-op size of the insn; we change it to
2 if an 0x66 prefix is seen */
indicating the prefix. */
UChar sorb = 0;
- /* If we don't set *size properly, this causes bbToIR_X86Instr to
- assert. */
- *size = 0;
+ /* Set result defaults. */
+ dres.whatNext = Dis_Continue;
+ dres.len = 0;
+ dres.continueAt = 0;
addr = t0 = t1 = t2 = t3 = t4 = t5 = t6 = IRTemp_INVALID;
- DIP("\t0x%x: ", guest_eip_bbstart+delta);
+ DIP("\t0x%x: ", guest_EIP_bbstart+delta);
+
+ /* We may be asked to update the guest EIP before going further. */
+ if (put_IP)
+ stmt( IRStmt_Put( OFFB_EIP, mkU32(guest_EIP_curr_instr)) );
/* Spot the client-request magic sequence. */
{
) {
DIP("%%edx = client_request ( %%eax )\n");
delta += 18;
- jmp_lit(Ijk_ClientReq, guest_eip_bbstart+delta);
- whatNext = Dis_StopHere;
+ jmp_lit(Ijk_ClientReq, guest_EIP_bbstart+delta);
+ dres.whatNext = Dis_StopHere;
goto decode_success;
}
}
else
if (0) {
vex_printf("vex x86->IR: ignoring LOCK prefix on: ");
- insn_verbose = True;
+ /* insn_verbose = True; */
}
/* In any case, skip the prefix. */
IRStmt_Exit(
binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
Ijk_EmWarn,
- IRConst_U32( ((Addr32)guest_eip_bbstart)+delta)
+ IRConst_U32( ((Addr32)guest_EIP_bbstart)+delta)
)
);
goto decode_success;
d32 = getUDisp16(delta);
delta += 2;
dis_ret(d32);
- whatNext = Dis_StopHere;
+ dres.whatNext = Dis_StopHere;
DIP("ret %d\n", (Int)d32);
break;
case 0xC3: /* RET */
dis_ret(0);
- whatNext = Dis_StopHere;
+ dres.whatNext = Dis_StopHere;
DIP("ret\n");
break;
case 0xE8: /* CALL J4 */
d32 = getUDisp32(delta); delta += 4;
- d32 += (guest_eip_bbstart+delta);
+ d32 += (guest_EIP_bbstart+delta);
/* (guest_eip_bbstart+delta) == return-to addr, d32 == call-to addr */
- if (d32 == guest_eip_bbstart+delta && getIByte(delta) >= 0x58
+ if (d32 == guest_EIP_bbstart+delta && getIByte(delta) >= 0x58
&& getIByte(delta) <= 0x5F) {
/* Specially treat the position-independent-code idiom
call X
since this generates better code, but for no other reason. */
Int archReg = getIByte(delta) - 0x58;
/* vex_printf("-- fPIC thingy\n"); */
- putIReg(4, archReg, mkU32(guest_eip_bbstart+delta));
+ putIReg(4, archReg, mkU32(guest_EIP_bbstart+delta));
delta++; /* Step over the POP */
DIP("call 0x%x ; popl %s\n",d32,nameIReg(4,archReg));
} else {
t1 = newTemp(Ity_I32);
assign(t1, binop(Iop_Sub32, getIReg(4,R_ESP), mkU32(4)));
putIReg(4, R_ESP, mkexpr(t1));
- storeLE( mkexpr(t1), mkU32(guest_eip_bbstart+delta));
- if (resteerOK && resteerOkFn((Addr64)(Addr32)d32)) {
+ storeLE( mkexpr(t1), mkU32(guest_EIP_bbstart+delta));
+ if (resteerOkFn((Addr64)(Addr32)d32)) {
/* follow into the call target. */
- whatNext = Dis_Resteer;
- *whereNext = d32;
+ dres.whatNext = Dis_Resteer;
+ dres.continueAt = (Addr64)(Addr32)d32;
} else {
jmp_lit(Ijk_Call,d32);
- whatNext = Dis_StopHere;
+ dres.whatNext = Dis_StopHere;
}
DIP("call 0x%x\n",d32);
}
/* It's important that all ArchRegs carry their up-to-date value
at this point. So we declare an end-of-block here, which
forces any TempRegs caching ArchRegs to be flushed. */
- jmp_lit(Ijk_Syscall,((Addr32)guest_eip_bbstart)+delta);
- whatNext = Dis_StopHere;
+ jmp_lit(Ijk_Syscall,((Addr32)guest_EIP_bbstart)+delta);
+ dres.whatNext = Dis_StopHere;
DIP("int $0x80\n");
break;
/* ------------------------ Jcond, byte offset --------- */
case 0xEB: /* Jb (jump, byte offset) */
- d32 = (((Addr32)guest_eip_bbstart)+delta+1) + getSDisp8(delta);
+ d32 = (((Addr32)guest_EIP_bbstart)+delta+1) + getSDisp8(delta);
delta++;
- if (resteerOK && resteerOkFn((Addr64)(Addr32)d32)) {
- whatNext = Dis_Resteer;
- *whereNext = d32;
+ if (resteerOkFn((Addr64)(Addr32)d32)) {
+ dres.whatNext = Dis_Resteer;
+ dres.continueAt = (Addr64)(Addr32)d32;
} else {
jmp_lit(Ijk_Boring,d32);
- whatNext = Dis_StopHere;
+ dres.whatNext = Dis_StopHere;
}
DIP("jmp-8 0x%x\n", d32);
break;
case 0xE9: /* Jv (jump, 16/32 offset) */
vassert(sz == 4); /* JRS added 2004 July 11 */
- d32 = (((Addr32)guest_eip_bbstart)+delta+sz) + getSDisp(sz,delta);
+ d32 = (((Addr32)guest_EIP_bbstart)+delta+sz) + getSDisp(sz,delta);
delta += sz;
- if (resteerOK && resteerOkFn((Addr64)(Addr32)d32)) {
- whatNext = Dis_Resteer;
- *whereNext = d32;
+ if (resteerOkFn((Addr64)(Addr32)d32)) {
+ dres.whatNext = Dis_Resteer;
+ dres.continueAt = (Addr64)(Addr32)d32;
} else {
jmp_lit(Ijk_Boring,d32);
- whatNext = Dis_StopHere;
+ dres.whatNext = Dis_StopHere;
}
DIP("jmp 0x%x\n", d32);
break;
case 0x7D: /* JGEb/JNLb (jump greater or equal) */
case 0x7E: /* JLEb/JNGb (jump less or equal) */
case 0x7F: /* JGb/JNLEb (jump greater) */
- d32 = (((Addr32)guest_eip_bbstart)+delta+1) + getSDisp8(delta);
+ d32 = (((Addr32)guest_EIP_bbstart)+delta+1) + getSDisp8(delta);
delta++;
- if (0 && resteerOK && resteerOkFn((Addr64)(Addr32)d32)) {
+ if (0 && resteerOkFn((Addr64)(Addr32)d32)) {
+ /* Unused experimental hack: speculatively follow one arm
+ of a conditional branch. */
/* Assume the branch is taken. So we need to emit a
side-exit to the insn following this one, on the negation
of the condition, and continue at the branch target
stmt( IRStmt_Exit(
mk_x86g_calculate_condition((X86Condcode)(1 ^ (opc - 0x70))),
Ijk_Boring,
- IRConst_U32(guest_eip_bbstart+delta) ) );
- whatNext = Dis_Resteer;
- *whereNext = d32;
+ IRConst_U32(guest_EIP_bbstart+delta) ) );
+ dres.whatNext = Dis_Resteer;
+ dres.continueAt = (Addr64)(Addr32)d32;
} else {
- jcc_01((X86Condcode)(opc - 0x70), (Addr32)(guest_eip_bbstart+delta), d32);
- whatNext = Dis_StopHere;
+ jcc_01((X86Condcode)(opc - 0x70), (Addr32)(guest_EIP_bbstart+delta), d32);
+ dres.whatNext = Dis_StopHere;
}
DIP("j%s-8 0x%x\n", name_X86Condcode(opc - 0x70), d32);
break;
manual says it depends on address size override,
which doesn't sound right to me. */
vassert(sz==4); /* possibly also OK for sz==2 */
- d32 = (((Addr32)guest_eip_bbstart)+delta+1) + getSDisp8(delta);
+ d32 = (((Addr32)guest_EIP_bbstart)+delta+1) + getSDisp8(delta);
delta++;
ty = szToITy(sz);
stmt( IRStmt_Exit(
/* REPNE prefix insn */
case 0xF2: {
- Addr32 eip_orig = guest_eip_bbstart + delta - 1;
+ Addr32 eip_orig = guest_EIP_bbstart + delta - 1;
vassert(sorb == 0);
abyte = getIByte(delta); delta++;
if (abyte == 0x66) { sz = 2; abyte = getIByte(delta); delta++; }
- whatNext = Dis_StopHere;
+ dres.whatNext = Dis_StopHere;
switch (abyte) {
/* According to the Intel manual, "repne movs" should never occur, but
case 0xAE: sz = 1; /* REPNE SCAS<sz> */
case 0xAF:
dis_REP_op ( X86CondNZ, dis_SCAS, sz, eip_orig,
- guest_eip_bbstart+delta, "repne scas" );
+ guest_EIP_bbstart+delta, "repne scas" );
break;
default:
/* REP/REPE prefix insn (for SCAS and CMPS, 0xF3 means REPE,
for the rest, it means REP) */
case 0xF3: {
- Addr32 eip_orig = guest_eip_bbstart + delta - 1;
+ Addr32 eip_orig = guest_EIP_bbstart + delta - 1;
vassert(sorb == 0);
abyte = getIByte(delta); delta++;
if (abyte == 0x66) { sz = 2; abyte = getIByte(delta); delta++; }
- whatNext = Dis_StopHere;
+ dres.whatNext = Dis_StopHere;
switch (abyte) {
case 0xA4: sz = 1; /* REP MOVS<sz> */
case 0xA5:
dis_REP_op ( X86CondAlways, dis_MOVS, sz, eip_orig,
- guest_eip_bbstart+delta, "rep movs" );
+ guest_EIP_bbstart+delta, "rep movs" );
break;
case 0xA6: sz = 1; /* REPE CMP<sz> */
case 0xA7:
dis_REP_op ( X86CondZ, dis_CMPS, sz, eip_orig,
- guest_eip_bbstart+delta, "repe cmps" );
+ guest_EIP_bbstart+delta, "repe cmps" );
break;
case 0xAA: sz = 1; /* REP STOS<sz> */
case 0xAB:
dis_REP_op ( X86CondAlways, dis_STOS, sz, eip_orig,
- guest_eip_bbstart+delta, "rep stos" );
+ guest_EIP_bbstart+delta, "rep stos" );
break;
//--
//-- case 0xAE: sz = 1; /* REPE SCAS<sz> */
DIP("rep nop (P4 pause)\n");
/* "observe" the hint. The Vex client needs to be careful not
to cause very long delays as a result, though. */
- jmp_lit(Ijk_Yield, ((Addr32)guest_eip_bbstart)+delta);
- whatNext = Dis_StopHere;
+ jmp_lit(Ijk_Yield, ((Addr32)guest_EIP_bbstart)+delta);
+ dres.whatNext = Dis_StopHere;
break;
//-- case 0xC3: /* REP RET */
/* ------------------------ (Grp5 extensions) ---------- */
case 0xFF: /* Grp5 Ev */
- delta = dis_Grp5 ( sorb, sz, delta, &whatNext );
+ delta = dis_Grp5 ( sorb, sz, delta, &dres );
break;
/* ------------------------ Escapes to 2-byte opcodes -- */
case 0x8D: /* JGEb/JNLb (jump greater or equal) */
case 0x8E: /* JLEb/JNGb (jump less or equal) */
case 0x8F: /* JGb/JNLEb (jump greater) */
- d32 = (((Addr32)guest_eip_bbstart)+delta+4) + getUDisp32(delta);
+ d32 = (((Addr32)guest_EIP_bbstart)+delta+4) + getUDisp32(delta);
delta += 4;
jcc_01( (X86Condcode)(opc - 0x80),
- (Addr32)(guest_eip_bbstart+delta),
+ (Addr32)(guest_EIP_bbstart+delta),
d32 );
- whatNext = Dis_StopHere;
+ dres.whatNext = Dis_StopHere;
DIP("j%s-32 0x%x\n", name_X86Condcode(opc - 0x80), d32);
break;
EIP should be up-to-date since it made so at the start of each
insn, but nevertheless be paranoid and update it again right
now. */
- stmt( IRStmt_Put( OFFB_EIP, mkU32(guest_eip_curr_instr) ) );
- jmp_lit(Ijk_NoDecode, guest_eip_curr_instr);
- whatNext = Dis_StopHere;
- *size = 0;
- return whatNext;
+ stmt( IRStmt_Put( OFFB_EIP, mkU32(guest_EIP_curr_instr) ) );
+ jmp_lit(Ijk_NoDecode, guest_EIP_curr_instr);
+ dres.whatNext = Dis_StopHere;
+ dres.len = 0;
+ return dres;
} /* switch (opc) for the main (primary) opcode switch. */
/* All decode successes end up here. */
DIP("\n");
- *size = delta - delta_start;
- return whatNext;
+ dres.len = delta - delta_start;
+ return dres;
}
#undef DIP
#undef DIS
+
+/*------------------------------------------------------------*/
+/*--- Top-level fn ---*/
+/*------------------------------------------------------------*/
+
+/* Disassemble a single instruction into IR. The instruction
+ is located in host memory at &guest_code[delta]. */
+
+DisResult disInstr_X86 ( IRBB* irbb_IN,
+ Bool put_IP,
+ Bool (*resteerOkFn) ( Addr64 ),
+ UChar* guest_code_IN,
+ Long delta,
+ Addr64 guest_IP,
+ VexArchInfo* archinfo,
+ Bool host_bigendian_IN )
+{
+ DisResult dres;
+
+ /* Set globals (see top of this file) */
+ guest_code = guest_code_IN;
+ irbb = irbb_IN;
+ host_is_bigendian = host_bigendian_IN;
+ guest_EIP_curr_instr = (Addr32)guest_IP;
+ guest_EIP_bbstart = (Addr32)toUInt(guest_IP - delta);
+
+ dres = disInstr_X86_WRK ( put_IP, resteerOkFn,
+ delta, archinfo );
+
+ return dres;
+}
+
+
/*--------------------------------------------------------------------*/
/*--- end guest-x86/toIR.c ---*/
/*--------------------------------------------------------------------*/
#include "host-amd64/hdefs.h"
#include "host-ppc32/hdefs.h"
+#include "guest-generic/bb_to_IR.h"
#include "guest-x86/gdefs.h"
#include "guest-amd64/gdefs.h"
#include "guest-arm/gdefs.h"
void (*ppInstr) ( HInstr* );
void (*ppReg) ( HReg );
HInstrArray* (*iselBB) ( IRBB*, VexArchInfo* );
- IRBB* (*bbToIR) ( UChar*, Addr64,
- VexGuestExtents*,
- Bool(*)(Addr64),
- Bool(*)(Addr64),
- Bool, VexArchInfo* );
Int (*emit) ( UChar*, Int, HInstr* );
IRExpr* (*specHelper) ( HChar*, IRExpr** );
Bool (*preciseMemExnsFn) ( Int, Int );
+ DisOneInstrFn disInstrFn;
+
VexGuestLayout* guest_layout;
Bool host_is_bigendian = False;
IRBB* irbb;
ppInstr = NULL;
ppReg = NULL;
iselBB = NULL;
- bbToIR = NULL;
emit = NULL;
specHelper = NULL;
preciseMemExnsFn = NULL;
+ disInstrFn = NULL;
guest_word_type = Ity_INVALID;
host_word_type = Ity_INVALID;
case VexArchX86:
preciseMemExnsFn = guest_x86_state_requires_precise_mem_exns;
- bbToIR = bbToIR_X86;
+ disInstrFn = disInstr_X86;
specHelper = guest_x86_spechelper;
guest_sizeB = sizeof(VexGuestX86State);
guest_word_type = Ity_I32;
case VexArchAMD64:
preciseMemExnsFn = guest_amd64_state_requires_precise_mem_exns;
- bbToIR = bbToIR_AMD64;
+ disInstrFn = disInstr_AMD64;
specHelper = guest_amd64_spechelper;
guest_sizeB = sizeof(VexGuestAMD64State);
guest_word_type = Ity_I64;
case VexArchARM:
preciseMemExnsFn = guest_arm_state_requires_precise_mem_exns;
- bbToIR = bbToIR_ARM;
+ disInstrFn = NULL; /* HACK */
specHelper = guest_arm_spechelper;
guest_sizeB = sizeof(VexGuestARMState);
guest_word_type = Ity_I32;
case VexArchPPC32:
preciseMemExnsFn = guest_ppc32_state_requires_precise_mem_exns;
- bbToIR = bbToIR_PPC32;
+ disInstrFn = disInstr_PPC32;
specHelper = guest_ppc32_spechelper;
guest_sizeB = sizeof(VexGuestPPC32State);
guest_word_type = Ity_I32;
" Front end "
"------------------------\n\n");
- irbb = bbToIR ( guest_bytes,
- guest_bytes_addr,
- guest_extents,
- byte_accessible,
- chase_into_ok,
- host_is_bigendian,
- archinfo_guest );
+ irbb = bb_to_IR ( guest_extents,
+ disInstrFn,
+ guest_bytes,
+ guest_bytes_addr,
+ chase_into_ok,
+ host_is_bigendian,
+ archinfo_guest,
+ guest_word_type );
if (irbb == NULL) {
/* Access failure. */
VexTranslateResult tres;
VexControl vcon;
VexGuestExtents vge;
- VexArchInfo vai;
+ VexArchInfo vai_x86, vai_amd64, vai_ppc32;
if (argc != 2) {
fprintf(stderr, "usage: vex file.org\n");
origbuf[i] = (UChar)u;
}
- LibVEX_default_VexArchInfo(&vai);
- vai.subarch = VexSubArchX86_sse1;
+ LibVEX_default_VexArchInfo(&vai_x86);
+ vai_x86.subarch = VexSubArchX86_sse1;
+
+ LibVEX_default_VexArchInfo(&vai_amd64);
+ vai_amd64.subarch = VexSubArch_NONE;
+
+ LibVEX_default_VexArchInfo(&vai_ppc32);
+ vai_ppc32.subarch = VexSubArchPPC32_AV;
+ vai_ppc32.ppc32_cache_line_szB = 128;
for (i = 0; i < TEST_N_ITERS; i++)
tres
= LibVEX_Translate (
-#if 0 /* ppc32 -> ppc32 */
- VexArchPPC32, VexSubArchPPC32_noAV,
- VexArchPPC32, VexSubArchPPC32_noAV,
-#endif
-#if 0 /* ppc32 -> x86 */
- VexArchPPC32, VexSubArchPPC32_noAV,
- VexArchX86, VexSubArchX86_sse2,
+#if 1 /* ppc32 -> ppc32 */
+ VexArchPPC32, &vai_ppc32,
+ VexArchPPC32, &vai_ppc32,
#endif
#if 0 /* amd64 -> amd64 */
- VexArchAMD64, VexSubArch_NONE,
- VexArchAMD64, VexSubArch_NONE,
+ VexArchAMD64, &vai_amd64,
+ VexArchAMD64, &vai_amd64,
#endif
-#if 1 /* x86 -> x86 */
- VexArchX86, &vai,
- VexArchX86, &vai,
+#if 0 /* x86 -> x86 */
+ VexArchX86, &vai_x86,
+ VexArchX86, &vai_x86,
#endif
-
origbuf, (Addr64)orig_addr, chase_into_not_ok,
&vge,
transbuf, N_TRANSBUF, &trans_used,
/* Copy this file (test_main.h.in) to test_main.h, and edit */
/* DEBUG RUN, ON V */
-#if 1
+#if 0
#define TEST_VSUPPORT True
#define TEST_N_ITERS 1
#define TEST_N_BBS 1
#endif
/* CHECKING RUN, ON V */
-#if 0
+#if 1
#define TEST_VSUPPORT True
#define TEST_N_ITERS 1
#define TEST_N_BBS 100000