]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
The logic that drove basic block to IR disassembly had been duplicated
authorJulian Seward <jseward@acm.org>
Sat, 2 Jul 2005 19:24:10 +0000 (19:24 +0000)
committerJulian Seward <jseward@acm.org>
Sat, 2 Jul 2005 19:24:10 +0000 (19:24 +0000)
over the 3 front ends (x86, amd64, ppc32).  Given the need to take
into account basic block chasing, adding of instruction marks, etc,
the logic is not completely straightforward, and so commoning it up is
a good thing.

git-svn-id: svn://svn.valgrind.org/vex/trunk@1247

15 files changed:
VEX/Makefile
VEX/priv/guest-amd64/gdefs.h
VEX/priv/guest-amd64/ghelpers.c
VEX/priv/guest-amd64/toIR.c
VEX/priv/guest-generic/bb_to_IR.c [new file with mode: 0644]
VEX/priv/guest-generic/bb_to_IR.h [new file with mode: 0644]
VEX/priv/guest-ppc32/gdefs.h
VEX/priv/guest-ppc32/ghelpers.c
VEX/priv/guest-ppc32/toIR.c
VEX/priv/guest-x86/gdefs.h
VEX/priv/guest-x86/ghelpers.c
VEX/priv/guest-x86/toIR.c
VEX/priv/main/vex_main.c
VEX/test_main.c
VEX/test_main.h

index 5b06d76002968b03aa4ebeff420edf0b0a27ff24..cfdff11704cc44e1ca033d4bc98e3dc39778a34f 100644 (file)
@@ -19,6 +19,7 @@ PRIV_HEADERS =        priv/host-x86/hdefs.h                   \
                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                  \
@@ -44,6 +45,7 @@ LIB_OBJS =    priv/ir/irdefs.o                        \
                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               \
@@ -203,6 +205,10 @@ priv/guest-generic/g_generic_x87.o: $(ALL_HEADERS) priv/guest-generic/g_generic_
        $(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
index d1f9c2001618066de653546c87272b73d893ce66..9e613b3c1d439ae4d11f1b94bd1691dff6ca9d15 100644 (file)
 /*--- 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
index c504fcc802c973645c7b0edff3f61936326818db..24c5ed0a54fe62a4fe5d974ae4abebeace6ae154 100644 (file)
@@ -40,6 +40,7 @@
 #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"
 
index d5a2e10bebebc4592b862060c8c3d7533f438b1c..0a5d7f2bc7779aa963328d577207cb39c06247c1 100644 (file)
@@ -91,6 +91,7 @@
 
 #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
@@ -143,8 +136,8 @@ static Bool  insn_verbose = False;
    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;
 
 
 /*------------------------------------------------------------*/
@@ -288,11 +281,11 @@ static void unimplemented ( HChar* str )
 }
 
 #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)
 
 
@@ -364,232 +357,6 @@ static void unimplemented ( HChar* str )
 #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.                                   ---*/
@@ -2278,7 +2045,7 @@ IRTemp disAMode ( Int* len, Prefix pfx, ULong delta,
       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);
@@ -2289,12 +2056,12 @@ IRTemp disAMode ( Int* len, Prefix pfx, ULong 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))));
          }
 
@@ -3724,7 +3491,7 @@ ULong dis_Grp4 ( Prefix pfx, ULong delta )
 
 /* 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;
@@ -3763,10 +3530,10 @@ ULong dis_Grp5 ( Prefix pfx, Int sz, ULong delta, DisResult* whatNext )
             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 */
@@ -3776,7 +3543,7 @@ ULong dis_Grp5 ( Prefix pfx, Int sz, ULong delta, DisResult* whatNext )
             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: 
@@ -3818,10 +3585,10 @@ ULong dis_Grp5 ( Prefix pfx, Int sz, ULong delta, DisResult* whatNext )
             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 */
@@ -3831,7 +3598,7 @@ ULong dis_Grp5 ( Prefix pfx, Int sz, ULong delta, DisResult* whatNext )
             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 */
@@ -4645,7 +4412,7 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
                   IRStmt_Exit(
                      binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
                      Ijk_EmWarn,
-                     IRConst_U64( guest_rip_bbstart+delta )
+                     IRConst_U64( guest_RIP_bbstart+delta )
                   )
                );
 
@@ -4687,7 +4454,7 @@ ULong dis_FPU ( /*OUT*/Bool* decode_ok,
                   IRStmt_Exit(
                      binop(Iop_CmpNE32, mkexpr(ew), mkU32(0)),
                      Ijk_EmWarn,
-                     IRConst_U64( guest_rip_bbstart+delta )
+                     IRConst_U64( guest_RIP_bbstart+delta )
                   )
                );
                break;
@@ -7919,20 +7686,16 @@ static IRExpr* mk64from16s ( IRTemp t3, IRTemp t2,
 /*--- 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;
@@ -7941,9 +7704,12 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
    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;
@@ -7956,16 +7722,21 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
    /* 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. */
    {
@@ -7987,8 +7758,8 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
          ) {
          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;
       }
    }
@@ -8512,7 +8283,7 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
          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;
@@ -11473,27 +11244,27 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
       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;
@@ -11676,14 +11447,14 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
       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;
@@ -11692,14 +11463,14 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
       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;
@@ -11721,12 +11492,12 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
    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;
 
@@ -12587,9 +12358,9 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
          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} */
@@ -12609,9 +12380,9 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
          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;
@@ -12624,9 +12395,9 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
          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} */
@@ -12646,9 +12417,9 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
          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 */
@@ -12982,7 +12753,7 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
 
    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 -- */
@@ -13218,12 +12989,12 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
       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;
 
@@ -13342,14 +13113,14 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
 
       /* =-=-=-=-=-=-=-=-=- 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;
 
@@ -13488,24 +13259,75 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
       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 ---*/
 /*--------------------------------------------------------------------*/
diff --git a/VEX/priv/guest-generic/bb_to_IR.c b/VEX/priv/guest-generic/bb_to_IR.c
new file mode 100644 (file)
index 0000000..d8dfae0
--- /dev/null
@@ -0,0 +1,247 @@
+
+/*--------------------------------------------------------------------*/
+/*---                                                              ---*/
+/*--- 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 ---*/
+/*--------------------------------------------------------------------*/
diff --git a/VEX/priv/guest-generic/bb_to_IR.h b/VEX/priv/guest-generic/bb_to_IR.h
new file mode 100644 (file)
index 0000000..3d26938
--- /dev/null
@@ -0,0 +1,156 @@
+
+/*--------------------------------------------------------------------*/
+/*---                                                              ---*/
+/*--- 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 ---*/
+/*--------------------------------------------------------------------*/
index 4a8161f60c829c6be7cedf7a8804766db181f6ba..7fc3e7547dc09d8f6f01ab1cbecefe1d5065d174 100644 (file)
 #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
@@ -86,6 +71,26 @@ 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                                 ---*/
 /*---------------------------------------------------------*/
index fb38a2ea2ac86fe0c6789388efdb8bd8f87fdf5c..70480ee47d64337c7347697989dc07aa1bd05ba2 100644 (file)
@@ -40,6 +40,7 @@
 #include "libvex.h"
 
 #include "main/vex_util.h"
+#include "guest-generic/bb_to_IR.h"
 #include "guest-ppc32/gdefs.h"
 
 
index 92e8a687078d62f0918be1300ee168c322c123ce..5ea96447940b341238746478d181079efc3b9b84 100644 (file)
@@ -64,6 +64,7 @@
 
 #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;
@@ -245,179 +242,6 @@ static void vex_printf_binary( UInt x, UInt len, Bool spaces )
 #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.                                   ---*/
@@ -491,9 +315,10 @@ static Int integerGuestRegOffset ( UInt archreg )
 {
    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);
@@ -1083,7 +908,7 @@ static void putReg_masked ( PPC32SPR reg, IRExpr* src, UInt mask )
             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)
                )
             );
       }
@@ -2483,7 +2308,7 @@ static IRExpr* branch_cond_ok( UInt BO, UInt BI )
 /*
   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] */
@@ -2512,7 +2337,7 @@ static Bool dis_branch ( UInt theInstr, DisResult *whatNext )
    /* 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;
     }
     
@@ -2521,12 +2346,12 @@ static Bool dis_branch ( UInt theInstr, DisResult *whatNext )
       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);
@@ -2548,12 +2373,12 @@ static Bool dis_branch ( UInt theInstr, DisResult *whatNext )
       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) );
       }
       
@@ -2562,7 +2387,7 @@ static Bool dis_branch ( UInt theInstr, DisResult *whatNext )
                          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:
@@ -2586,13 +2411,13 @@ static Bool dis_branch ( UInt theInstr, DisResult *whatNext )
          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);
@@ -2618,13 +2443,13 @@ static Bool dis_branch ( UInt theInstr, DisResult *whatNext )
          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);
@@ -2640,7 +2465,7 @@ static Bool dis_branch ( UInt theInstr, DisResult *whatNext )
       return False;
    }
     
-   *whatNext = Dis_StopHere;
+   dres->whatNext = Dis_StopHere;
    return True;
 }
 
@@ -2740,7 +2565,7 @@ static Bool dis_cond_logic ( UInt theInstr )
 /*
   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");
@@ -2753,10 +2578,10 @@ static Bool dis_syslink ( UInt theInstr, DisResult *whatNext )
    /* 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;
 }
 
@@ -3280,7 +3105,7 @@ vassert(0);
   Cache Management Instructions
 */
 static Bool dis_cache_manage ( UInt         theInstr, 
-                               DisResult*   whatNext,
+                               DisResult*   dres,
                                VexArchInfo* guest_archinfo )
 {
    /* X-Form */
@@ -3377,8 +3202,8 @@ static Bool dis_cache_manage ( UInt         theInstr,
       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;
    }
 
@@ -5636,38 +5461,35 @@ static Bool dis_av_fp_convert ( UInt theInstr )
 /*------------------------------------------------------------*/
 
 /* 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
@@ -5689,12 +5511,12 @@ static DisResult disInstr ( /*IN*/  Bool    resteerOK,
           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;
       }
    }
@@ -5756,12 +5578,12 @@ static DisResult disInstr ( /*IN*/  Bool    resteerOK,
 
    /* 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 */
@@ -5874,7 +5696,7 @@ static DisResult disInstr ( /*IN*/  Bool    resteerOK,
 
       /* 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 */
@@ -5973,7 +5795,7 @@ static DisResult disInstr ( /*IN*/  Bool    resteerOK,
       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;
 
@@ -6191,27 +6013,59 @@ static DisResult disInstr ( /*IN*/  Bool    resteerOK,
       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 ---*/
 /*--------------------------------------------------------------------*/
index 29a1fabec7956bed43bb07d39cb35df58740738b..8c147aa1ddcfa802e8f6ff6de596013677809237 100644 (file)
 /*--- 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
index d3954590afc4436a1b4c7dc8c40aa0161d73c981..f64b44574e9985590acc783f0988578d99932b72 100644 (file)
@@ -40,6 +40,7 @@
 #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"
 
index b6199d720c83f6310f20773bbfa66a9191f8b7bc..712af4e77afd48ad15127fd081071557a649dc6b 100644 (file)
 
 #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)
 
 
@@ -199,221 +196,6 @@ static Bool  insn_verbose = False;
 #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.                                     ---*/
@@ -1488,7 +1270,7 @@ IRExpr* handleSegOverride ( UChar sorb, IRExpr* virtual )
       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 )
       )
    );
 
@@ -2908,7 +2690,7 @@ UInt dis_Grp4 ( UChar sorb, UInt delta )
 
 /* 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;
@@ -2937,14 +2719,14 @@ UInt dis_Grp5 ( UChar sorb, Int sz, UInt delta, DisResult* whatNext )
             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(
@@ -2977,14 +2759,14 @@ UInt dis_Grp5 ( UChar sorb, Int sz, UInt delta, DisResult* whatNext )
             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);
@@ -3778,7 +3560,7 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt 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)
                   )
                );
 
@@ -3820,7 +3602,7 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt 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;
@@ -4616,7 +4398,7 @@ UInt dis_FPU ( Bool* decode_ok, UChar sorb, UInt 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)
                   )
                );
 
@@ -6990,19 +6772,15 @@ static IRExpr* mk64from16s ( IRTemp t3, IRTemp t2,
 /*------------------------------------------------------------*/
 
 /* 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;
@@ -7011,12 +6789,15 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
    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 */
@@ -7027,13 +6808,18 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
       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. */
    {
@@ -7055,8 +6841,8 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
          ) {
          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;
       }
    }
@@ -7087,7 +6873,7 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
       else
       if (0) {
          vex_printf("vex x86->IR: ignoring LOCK prefix on: ");
-         insn_verbose = True;
+         /* insn_verbose = True; */
       }
 
       /* In any case, skip the prefix. */
@@ -7526,7 +7312,7 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
          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;
@@ -10331,20 +10117,20 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
       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
@@ -10354,7 +10140,7 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
             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 {
@@ -10362,14 +10148,14 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
          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);
       }
@@ -10574,36 +10360,36 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
       /* 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;
@@ -10624,9 +10410,11 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
    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
@@ -10635,12 +10423,12 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
          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;
@@ -10649,7 +10437,7 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
                  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(
@@ -11320,12 +11108,12 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
 
    /* 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
@@ -11345,7 +11133,7 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
       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:
@@ -11357,30 +11145,30 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
    /* 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> */
@@ -11393,8 +11181,8 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
          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 */
@@ -11643,7 +11431,7 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
    /* ------------------------ (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 -- */
@@ -11907,12 +11695,12 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
       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;
 
@@ -12156,11 +11944,11 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
       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. */
 
@@ -12168,13 +11956,46 @@ DisResult disInstr ( /*IN*/  Bool         resteerOK,
    /* 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 ---*/
 /*--------------------------------------------------------------------*/
index 3d345fdbb31b2e3ffc2ab2e5ab1ce4ce5760b2e4..52e66b059c937db9dc4c4cdc5a5d1cc4346123ce 100644 (file)
@@ -49,6 +49,7 @@
 #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"
@@ -208,15 +209,12 @@ VexTranslateResult LibVEX_Translate (
    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;
@@ -238,10 +236,10 @@ VexTranslateResult LibVEX_Translate (
    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;
 
@@ -319,7 +317,7 @@ VexTranslateResult LibVEX_Translate (
 
       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;
@@ -331,7 +329,7 @@ VexTranslateResult LibVEX_Translate (
 
       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;
@@ -341,7 +339,7 @@ VexTranslateResult LibVEX_Translate (
 
       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;
@@ -351,7 +349,7 @@ VexTranslateResult LibVEX_Translate (
 
       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;
@@ -377,13 +375,14 @@ VexTranslateResult LibVEX_Translate (
                    " 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. */
index 854dbbf9c99d8c549fc0511930810271c0e8a2b1..dc5f0548110a3ffa194e463f70d815977bf54755 100644 (file)
@@ -66,7 +66,7 @@ int main ( int argc, char** argv )
    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");
@@ -123,29 +123,31 @@ int main ( int argc, char** argv )
          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,
index 6bd5e0f5e2988d8e9e232bd1b0b9e6043da06a20..0005fd6c0f756067eaa61f8e31d16349e005e48d 100644 (file)
@@ -2,7 +2,7 @@
 /* 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
@@ -10,7 +10,7 @@
 #endif
 
 /* CHECKING RUN, ON V */
-#if 0
+#if 1
 #define TEST_VSUPPORT  True
 #define TEST_N_ITERS   1
 #define TEST_N_BBS     100000