]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Ceri's first attempts at figuring out what the heck is going on!
authorCerion Armour-Brown <cerion@valgrind.org>
Thu, 2 Dec 2004 20:19:22 +0000 (20:19 +0000)
committerCerion Armour-Brown <cerion@valgrind.org>
Thu, 2 Dec 2004 20:19:22 +0000 (20:19 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@607

VEX/priv/guest-arm/gdefs.h
VEX/priv/guest-arm/ghelpers.c
VEX/priv/guest-arm/toIR.c

index 16752d790b417c8153089772f2a872bc47946309..c5b3e48b77843b026f261c6b78af0f22e47df39a 100644 (file)
@@ -154,7 +154,11 @@ enum {
     ARMG_CC_OP_COPY,    /* DEP1 = current flags, DEP2 = 0 */
                         /* just copy DEP1 to output */
 
-    ARMG_CC_OP_ADD      /* 1   DEP1 = argL, DEP2 = argR */
+    ARMG_CC_OP_MOV,
+
+
+
+    ARMG_CC_OP_NUMBER
 };
 
 /* requires further study */
@@ -165,29 +169,33 @@ enum {
 
 typedef
    enum {
-      ARMCondEQ     = 0,  /* equal                               */
-      ARMCondNE     = 1,  /* not equal                           */
+      ARMCondEQ     = 0,  /* equal                               : Z=1 */
+      ARMCondNE     = 1,  /* not equal                           : Z=0 */
 
-      ARMCondHS     = 2,  /* >=u (higher or same)                */
-      ARMCondLO     = 3,  /* <u  (lower)                         */
+      ARMCondHS     = 2,  /* >=u (higher or same)                : C=1 */
+      ARMCondLO     = 3,  /* <u  (lower)                         : C=0 */
 
-      ARMCondMI     = 4,  /* minus (negative)                    */
-      ARMCondPL     = 5,  /* plus (zero or +ve)                  */
+      ARMCondMI     = 4,  /* minus (negative)                    : N=1 */
+      ARMCondPL     = 5,  /* plus (zero or +ve)                  : N=0 */
 
-      ARMCondVS     = 6,  /* overflow                            */
-      ARMCondVC     = 7,  /* no overflow                         */
+      ARMCondVS     = 6,  /* overflow                            : V=1 */
+      ARMCondVC     = 7,  /* no overflow                         : V=0 */
 
-      ARMCondHI     = 8,  /* >u   (higher)                       */
-      ARMCondLS     = 9,  /* <=u  (lower or same)                */
+      ARMCondHI     = 8,  /* >u   (higher)                       : C=1 && Z=0 */
+      ARMCondLS     = 9,  /* <=u  (lower or same)                : C=0 || Z=1 */
 
-      ARMCondGE     = 10, /* >=s (signed greater or equal)       */
-      ARMCondLT     = 11, /* <s  (signed less than)              */
+      ARMCondGE     = 10, /* >=s (signed greater or equal)       : N=V */
+      ARMCondLT     = 11, /* <s  (signed less than)              : N!=V */
 
-      ARMCondGT     = 12, /* >s  (signed greater)                */
-      ARMCondLE     = 13, /* <=s (signed less or equal)          */
+      ARMCondGT     = 12, /* >s  (signed greater)                : Z=0 && N=V */
+      ARMCondLE     = 13, /* <=s (signed less or equal)          : Z=1 || N!=V */
 
-      ARMCondAL     = 14, /* always (unconditional)              */
-      ARMCondNV     = 15  /* never (basically undefined meaning) */
+      ARMCondAL     = 14, /* always (unconditional)              : */
+      ARMCondNV     = 15  /* never (basically undefined meaning) : */
+                          /* NB: ARM have deprecated the use of the NV condition code
+                             - you are now supposed to use MOV R0,R0 as a noop
+                               rather than MOVNV R0,R0 as was previously recommended.
+                             Future processors may have the NV condition code reused to do other things.  */
    }
    ARMCondcode;
 
index b0324c5f7929b7fae4a684ffc87c17ac7b199918..9539c2cf495ab6036fc8f0f32f88d93fc6e06b39 100644 (file)
 */
 
 
+#if 0
+#define PREAMBLE(__data_bits)                                  \
+   /* const */ UInt DATA_MASK                                  \
+      = __data_bits==8 ? 0xFF                                  \
+                       : (__data_bits==16 ? 0xFFFF             \
+                                          : 0xFFFFFFFF);       \
+   /* const */ UInt SIGN_MASK = 1 << (__data_bits - 1);                \
+   /* const */ UInt CC_DEP1 = cc_dep1_formal;                  \
+   /* const */ UInt CC_DEP2 = cc_dep2_formal;                  \
+   /* const */ UInt CC_NDEP = cc_ndep_formal;                  \
+   /* Four bogus assignments, which hopefully gcc can     */   \
+   /* optimise away, and which stop it complaining about  */   \
+   /* unused variables.                                   */   \
+   SIGN_MASK = SIGN_MASK;                                      \
+   DATA_MASK = DATA_MASK;                                      \
+   CC_DEP2 = CC_DEP2;                                          \
+   CC_NDEP = CC_NDEP;
+#endif
+
+/*-------------------------------------------------------------*/
+
+#define ACTIONS_MOV()                                          \
+{                                                              \
+   { Int nf, zf, cf;                                           \
+     Int argL, argR, res;                                      \
+   }                                                           \
+}
+/*
+  Need to calc the shift op...
+  
+*/
+
+/*
+#define ACTIONS_ADD()                                          \
+{                                                              \
+   PREAMBLE(32);                                               \
+   { Int cf, pf, af, zf, sf, of;                               \
+     Int argL, argR, res;                                      \
+     argL = CC_DEP1;                                           \
+     argR = CC_DEP2;                                           \
+     res  = argL + argR;                                       \
+     cf = (UInt)res < (UInt)argL;                              \
+     pf = parity_table[(UChar)res];                            \
+     af = (res ^ argL ^ argR) & 0x10;                          \
+     zf = ((UInt)res == 0) << 6;                               \
+     sf = lshift(res, 8 - DATA_BITS) & 0x80;                   \
+     of = lshift((argL ^ argR ^ -1) & (argL ^ res),            \
+                 12 - DATA_BITS) & X86G_CC_MASK_O;             \
+     return cf | pf | af | zf | sf | of;                       \
+*/
+
+
+
 
 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
 /* Calculate all the 4 flags from the supplied thunk parameters. */
-UInt calculate_eflags_all ( UInt cc_op, 
-                            UInt cc_dep1_formal, 
-                            UInt cc_dep2_formal )
+UInt armg_calculate_flags_all ( UInt cc_op, 
+                                UInt cc_dep1_formal, 
+                                UInt cc_dep2_formal )
 {
    switch (cc_op) {
+
+       /* CAB: ... all amd ops... */
+
+       case ARMG_CC_OP_MOV:  ACTIONS_MOV();
+
+
       default:
          /* shouldn't really make these calls from generated code */
-         vex_printf("calculate_eflags_all(ARM)( %d, 0x%x, 0x%x )\n",
+         vex_printf("armg_calculate_flags_all(ARM)( %d, 0x%x, 0x%x )\n",
                     cc_op, cc_dep1_formal, cc_dep2_formal );
-         vpanic("calculate_eflags_all(ARM)");
+         vpanic("armg_calculate_flags_all(ARM)");
    }
 }
 
 
 /* CALLED FROM GENERATED CODE: CLEAN HELPER */
 /* returns 1 or 0 */
-/*static*/ UInt calculate_condition ( UInt/*Condcode*/ cond, 
-                                      UInt cc_op, 
-                                      UInt cc_dep1, 
-                                      UInt cc_dep2 )
+/*static*/
+UInt armg_calculate_condition ( UInt/*ARMCondcode*/ cond, 
+                               UInt cc_op, 
+                               UInt cc_dep1, 
+                               UInt cc_dep2 )
 {
-  //UInt nzvc = calculate_eflags_all(cc_op, cc_dep1, cc_dep2);
+   UInt nf,zf,vf,cf;
+   UInt inv = cond & 1;
+
+   UInt nzvc = armg_calculate_flags_all(cc_op, cc_dep1, cc_dep2);
 
    switch (cond) {
-      default:
-         /* shouldn't really make these calls from generated code */
-         vex_printf("calculate_condition(ARM)( %d, %d, 0x%x, 0x%x )\n",
-                    cond, cc_op, cc_dep1, cc_dep2 );
-         vpanic("calculate_condition(ARM)");
+   case ARMCondEQ:    // Z=1         => z
+   case ARMCondNE:    // Z=0
+       zf = nzvc >> ARMG_CC_SHIFT_Z;
+       return 1 & (inv ^ zf);
+
+   case ARMCondHS:    // C=1         => c
+   case ARMCondLO:    // C=0
+       cf = nzvc >> ARMG_CC_SHIFT_C;
+       return 1 & (inv ^ cf);
+
+   case ARMCondMI:    // N=1         => n
+   case ARMCondPL:    // N=0
+       nf = nzvc >> ARMG_CC_SHIFT_N;
+       return 1 & (inv ^ nf);
+
+   case ARMCondVS:    // V=1         => v
+   case ARMCondVC:    // V=0
+       vf = nzvc >> ARMG_CC_SHIFT_V;
+       return 1 & (inv ^ vf);
+
+   case ARMCondHI:    // C=1 && Z=0   => c & ~z
+   case ARMCondLS:    // C=0 || Z=1
+       cf = nzvc >> ARMG_CC_SHIFT_C;
+       zf = nzvc >> ARMG_CC_SHIFT_Z;
+       return 1 & (inv ^ (cf & ~zf));
+
+   case ARMCondGE:    // N=V          => ~(n^v)
+   case ARMCondLT:    // N!=V
+       nf = nzvc >> ARMG_CC_SHIFT_N;
+       vf = nzvc >> ARMG_CC_SHIFT_V;
+       return 1 & (inv ^ ~(nf ^ vf));
+
+   case ARMCondGT:    // Z=0 && N=V   => (~z & ~(n^v)  =>  ~(z | (n^v)
+   case ARMCondLE:    // Z=1 || N!=V
+       nf = nzvc >> ARMG_CC_SHIFT_N;
+       vf = nzvc >> ARMG_CC_SHIFT_V;
+       zf = nzvc >> ARMG_CC_SHIFT_Z;
+       return 1 & (inv ^ ~(zf | (nf ^ vf)));
+
+   case ARMCondAL:   // should never get here: Always => no flags to calc
+   case ARMCondNV:   // should never get here: Illegal instr
+   default:
+       /* shouldn't really make these calls from generated code */
+       vex_printf("armg_calculate_condition(ARM)( %d, %d, 0x%x, 0x%x )\n",
+                 cond, cc_op, cc_dep1, cc_dep2 );
+       vpanic("armg_calculate_condition(ARM)");
    }
 }
 
@@ -94,14 +198,12 @@ UInt calculate_eflags_all ( UInt cc_op,
 /* Used by the optimiser to try specialisations.  Returns an
    equivalent expression, or NULL if none. */
 
-#if 0
 static Bool isU32 ( IRExpr* e, UInt n )
 {
    return e->tag == Iex_Const
           && e->Iex.Const.con->tag == Ico_U32
           && e->Iex.Const.con->Ico.U32 == n;
 }
-#endif
 IRExpr* guest_arm_spechelper ( Char* function_name,
                                IRExpr** args )
 {
@@ -114,49 +216,50 @@ IRExpr* guest_arm_spechelper ( Char* function_name,
 /*----------------------------------------------*/
 
 /* VISIBLE TO LIBVEX CLIENT */
+#if 0
 void LibVEX_GuestARM_put_flags ( UInt eflags_native,
                                  /*OUT*/VexGuestARMState* vex_state )
 {
    vassert(0); // FIXME
 #if 0
+   // CAB: what does this do?!
    vex_state->guest_DFLAG
       = (eflags_native & (1<<10)) ? 0xFFFFFFFF : 0x00000001;
    vex_state->guest_IDFLAG
       = (eflags_native & (1<<21)) ? 1 : 0;
+#endif
 
-   /* Mask out everything except O S Z A C P. */
+   /* Mask out everything except N Z V C. */
    eflags_native
-      &= (CC_MASK_C | CC_MASK_P | CC_MASK_A 
-          | CC_MASK_Z | CC_MASK_S | CC_MASK_O);
+      &= (ARMG_CC_MASK_N | ARMG_CC_MASK_Z | ARMG_CC_MASK_V | ARMG_CC_MASK_C);
 
-   vex_state->guest_CC_OP   = CC_OP_COPY;
+   vex_state->guest_CC_OP   = ARMG_CC_OP_COPY;
    vex_state->guest_CC_DEP1 = eflags_native;
    vex_state->guest_CC_DEP2 = 0;
-   vex_state->guest_CC_NDEP = 0; /* unnecessary paranoia */
-#endif
 }
-
+#endif
 
 /* VISIBLE TO LIBVEX CLIENT */
 UInt LibVEX_GuestARM_get_eflags ( /*IN*/VexGuestARMState* vex_state )
 {
    vassert(0); // FIXME
-#if 0
-   UInt eflags = calculate_eflags_all(
+
+   UInt eflags = armg_calculate_eflags_all(
                     vex_state->guest_CC_OP,
                     vex_state->guest_CC_DEP1,
-                    vex_state->guest_CC_DEP2,
-                    vex_state->guest_CC_NDEP
+                    vex_state->guest_CC_DEP2
                  );
+#if 0
+   // CAB: what does this do?!
    UInt dflag = vex_state->guest_DFLAG;
    vassert(dflag == 1 || dflag == 0xFFFFFFFF);
    if (dflag == 0xFFFFFFFF)
       eflags |= (1<<10);
    if (vex_state->guest_IDFLAG == 1)
       eflags |= (1<<21);
-                                            
-   return eflags;
 #endif
+
+   return eflags;
 }
 
 /* VISIBLE TO LIBVEX CLIENT */
@@ -179,10 +282,16 @@ void LibVEX_GuestARM_initialise ( /*OUT*/VexGuestARMState* vex_state )
    vex_state->guest_R14 = 0;
    vex_state->guest_R15 = 0;
 
-   vex_state->guest_CC_OP   = ARMG_CC_OP_COPY;
+   // CAB: Want this?
+   //vex_state->guest_SYSCALLNO = 0;
+
+   vex_state->guest_CC_OP   = 0;// CAB: ? ARMG_CC_OP_COPY;
    vex_state->guest_CC_DEP1 = 0;
    vex_state->guest_CC_DEP2 = 0;
 
+   // CAB: Want this?   
+   //vex_state->guest_EMWARN = 0;
+
    vex_state->guest_SYSCALLNO = 0;
 }
 
index a1e46433ad1c69885a3d26b9aee0106cfe406827..6d76c11f2825911ddb2bd9dcdcac92e26071328b 100644 (file)
@@ -88,9 +88,30 @@ static IRBB* irbb;
 /*------------------------------------------------------------*/
 
 #define OFFB_R0       offsetof(VexGuestARMState,guest_R0)
-// etc etc
+#define OFFB_R1       offsetof(VexGuestARMState,guest_R1)
+#define OFFB_R2       offsetof(VexGuestARMState,guest_R2)
+#define OFFB_R3       offsetof(VexGuestARMState,guest_R3)
+#define OFFB_R4       offsetof(VexGuestARMState,guest_R4)
+#define OFFB_R5       offsetof(VexGuestARMState,guest_R5)
+#define OFFB_R6       offsetof(VexGuestARMState,guest_R6)
+#define OFFB_R7       offsetof(VexGuestARMState,guest_R7)
+#define OFFB_R8       offsetof(VexGuestARMState,guest_R8)
+#define OFFB_R9       offsetof(VexGuestARMState,guest_R9)
+#define OFFB_R10      offsetof(VexGuestARMState,guest_R10)
+#define OFFB_R11      offsetof(VexGuestARMState,guest_R11)
+#define OFFB_R12      offsetof(VexGuestARMState,guest_R12)
+#define OFFB_R13      offsetof(VexGuestARMState,guest_R13)
+#define OFFB_R14      offsetof(VexGuestARMState,guest_R14)
 #define OFFB_R15      offsetof(VexGuestARMState,guest_R15)
 
+// CAB: ? guest_SYSCALLNO;
+
+#define OFFB_CC_OP    offsetof(VexGuestARMState,guest_CC_OP)
+#define OFFB_CC_DEP1  offsetof(VexGuestARMState,guest_CC_DEP1)
+#define OFFB_CC_DEP2  offsetof(VexGuestARMState,guest_CC_DEP2)
+
+// CAB: ? guest_EMWARN;
+
 
 /*------------------------------------------------------------*/
 /*--- Disassemble an entire basic block                    ---*/
@@ -325,7 +346,7 @@ static UInt getUDisp ( Int size, UInt delta )
       case 4: return getUDisp32(delta);
       case 2: return getUDisp16(delta);
       case 1: return getUChar(delta);
-      default: vpanic("getUDisp(x86)");
+      default: vpanic("getUDisp(ARM)");
    }
    return 0; /*notreached*/
 }
@@ -352,7 +373,7 @@ static UInt getSDisp ( Int size, UInt delta )
       case 4: return getUDisp32(delta);
       case 2: return getSDisp16(delta);
       case 1: return getSDisp8(delta);
-      default: vpanic("getSDisp(x86)");
+      default: vpanic("getSDisp(ARM)");
   }
   return 0; /*notreached*/
 }
@@ -373,7 +394,7 @@ static IRType szToITy ( Int n )
       case 1: return Ity_I8;
       case 2: return Ity_I16;
       case 4: return Ity_I32;
-      default: vpanic("szToITy(x86)");
+      default: vpanic("szToITy(ARM)");
    }
 }
 
@@ -384,13 +405,25 @@ static Int integerGuestRegOffset ( UInt archreg )
    vassert(!host_is_bigendian);   //TODO: is this necessary?
 
    switch (archreg) {
-      case  0: return offsetof(VexGuestARMState,guest_R0);
-      //etc etc
+      case  0: return offsetof(VexGuestARMState, guest_R0);
+      case  1: return offsetof(VexGuestARMState, guest_R1);
+      case  2: return offsetof(VexGuestARMState, guest_R2);
+      case  3: return offsetof(VexGuestARMState, guest_R3);
+      case  4: return offsetof(VexGuestARMState, guest_R4);
+      case  5: return offsetof(VexGuestARMState, guest_R5);
+      case  6: return offsetof(VexGuestARMState, guest_R6);
+      case  7: return offsetof(VexGuestARMState, guest_R7);
+      case  8: return offsetof(VexGuestARMState, guest_R8);
+      case  9: return offsetof(VexGuestARMState, guest_R9);
+      case 10: return offsetof(VexGuestARMState,guest_R10);
+      case 11: return offsetof(VexGuestARMState,guest_R11);
+      case 12: return offsetof(VexGuestARMState,guest_R12);
+      case 13: return offsetof(VexGuestARMState,guest_R13);
+      case 14: return offsetof(VexGuestARMState,guest_R14);
       case 15: return offsetof(VexGuestARMState,guest_R15);
    }
 
-   /* NOTREACHED */
-   vpanic("integerGuestRegOffset(arm,le)");
+   vpanic("integerGuestRegOffset(arm,le)"); /*notreached*/
 }
 
 static IRExpr* getIReg ( UInt archreg )
@@ -455,7 +488,7 @@ static IRExpr* mkU ( IRType ty, UInt i )
    if (ty == Ity_I32) return mkU32(i);
    /* If this panics, it usually means you passed a size (1,2,4)
       value as the IRType, rather than a real IRType. */
-   vpanic("mkU(x86)");
+   vpanic("mkU(ARM)");
 }
 
 static IRExpr* loadLE ( IRType ty, IRExpr* data )
@@ -488,86 +521,109 @@ static IROp mkWidenOp ( Int szSmall, Int szBig, Bool signd )
    if (szSmall == 2 && szBig == 4) {
       return signd ? Iop_16Sto32 : Iop_16Uto32;
    }
-   vpanic("mkWidenOp(x86,guest)");
+   vpanic("mkWidenOp(ARM,guest)");
 }
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
 /*------------------------------------------------------------*/
 /*--- Helpers for %eflags.                                 ---*/
 /*------------------------------------------------------------*/
-#if 0
-// Ceri: you'll need to make simplified versions of these
-// for arm
+
 /* -------------- Evaluating the flags-thunk. -------------- */
 
 /* Build IR to calculate all the eflags from stored
-   CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression ::
-   Ity_I32. */
-static IRExpr* mk_x86g_calculate_eflags_all ( void )
+   CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.
+   Returns an expression :: Ity_I32. */
+static IRExpr* mk_armg_calculate_flags_all ( void )
 {
    IRExpr** args
-      = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP,   Ity_I32),
+      = mkIRExprVec_3( IRExpr_Get(OFFB_CC_OP,   Ity_I32),
                        IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
-                       IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
-                       IRExpr_Get(OFFB_CC_NDEP, Ity_I32) );
+                       IRExpr_Get(OFFB_CC_DEP2, Ity_I32) );
    IRExpr* call
       = mkIRExprCCall(
            Ity_I32,
            0/*regparm*/, 
-           "x86g_calculate_eflags_all", &x86g_calculate_eflags_all,
+           "armg_calculate_flags_all", &armg_calculate_flags_all,
            args
         );
-   /* Exclude OP and NDEP from definedness checking.  We're only
+
+   /* Exclude OP from definedness checking.  We're only
       interested in DEP1 and DEP2. */
-   call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
+   call->Iex.CCall.cee->mcx_mask = 1;
    return call;
 }
 
+
+
 /* Build IR to calculate some particular condition from stored
-   CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression ::
-   Ity_Bit. */
-static IRExpr* mk_x86g_calculate_condition ( X86Condcode cond )
+   CC_OP/CC_DEP1/CC_DEP2.  Returns an expression
+*/
+static IRExpr* mk_armg_calculate_condition ( ARMCondcode cond )
 {
    IRExpr** args
-      = mkIRExprVec_5( mkU32(cond),
+      = mkIRExprVec_4( mkU32(cond),
                        IRExpr_Get(OFFB_CC_OP,  Ity_I32),
                        IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
-                       IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
-                       IRExpr_Get(OFFB_CC_NDEP, Ity_I32) );
+                       IRExpr_Get(OFFB_CC_DEP2, Ity_I32) );
    IRExpr* call
       = mkIRExprCCall(
            Ity_I32,
            0/*regparm*/, 
-           "x86g_calculate_condition", &x86g_calculate_condition,
+           "armg_calculate_condition", &armg_calculate_condition,
            args
         );
-   /* Exclude the requested condition, OP and NDEP from definedness
+
+   /* Exclude the requested condition and OP from definedness
       checking.  We're only interested in DEP1 and DEP2. */
-   call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<1) | (1<<4);
+   call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<1);
    return unop(Iop_32to1, call);
 }
 
+
+
+#if 0
+/* CAB: This needed?
+   j removed armg_calculate_eflags_c() from ghelpers.c ?
+*/
 /* Build IR to calculate just the carry flag from stored
-   CC_OP/CC_DEP1/CC_DEP2/CC_NDEP.  Returns an expression :: Ity_I32. */
-static IRExpr* mk_x86g_calculate_eflags_c ( void )
+   CC_OP/CC_DEP1/CC_DEP2.  Returns an expression :: Ity_I32. */
+static IRExpr* mk_armg_calculate_eflags_c ( void )
 {
    IRExpr** args
-      = mkIRExprVec_4( IRExpr_Get(OFFB_CC_OP,   Ity_I32),
+      = mkIRExprVec_3( IRExpr_Get(OFFB_CC_OP,   Ity_I32),
                        IRExpr_Get(OFFB_CC_DEP1, Ity_I32),
-                       IRExpr_Get(OFFB_CC_DEP2, Ity_I32),
-                       IRExpr_Get(OFFB_CC_NDEP, Ity_I32) );
+                       IRExpr_Get(OFFB_CC_DEP2, Ity_I32) );
    IRExpr* call
       = mkIRExprCCall(
            Ity_I32,
            0/*regparm*/, 
-           "x86g_calculate_eflags_c", &x86g_calculate_eflags_c,
+           "armg_calculate_eflags_c", &armg_calculate_eflags_c,
            args
         );
-   /* Exclude OP and NDEP from definedness checking.  We're only
+   /* Exclude OP from definedness checking.  We're only
       interested in DEP1 and DEP2. */
-   call->Iex.CCall.cee->mcx_mask = (1<<0) | (1<<3);
+   call->Iex.CCall.cee->mcx_mask = 1;
    return call;
 }
+#endif
+
+
+
+
 
 
 /* -------------- Building the flags-thunk. -------------- */
@@ -625,7 +681,7 @@ static IRExpr* narrowTo ( IRType dst_ty, IRExpr* e )
    vex_printf(", ");
    ppIRType(dst_ty);
    vex_printf("\n");
-   vpanic("narrowTo(x86)");
+   vpanic("narrowTo(ARM)");
 }
 
 
@@ -633,19 +689,10 @@ static IRExpr* narrowTo ( IRType dst_ty, IRExpr* e )
    auto-sized up to the real op. */
 
 static 
-void setFlags_DEP1_DEP2 ( IROp op8, IRTemp dep1, IRTemp dep2, IRType ty )
+void setFlags_DEP1_DEP2 ( IROp op, IRTemp dep1, IRTemp dep2, IRType ty )
 {
-   Int ccOp = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2);
-
-   vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
 
-   switch (op8) {
-      case Iop_Add8: ccOp += X86G_CC_OP_ADDB;   break;
-      case Iop_Sub8: ccOp += X86G_CC_OP_SUBB;   break;
-      default:       ppIROp(op8);
-                     vpanic("setFlags_DEP1_DEP2(x86)");
-   }
-   stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(ccOp)) );
+   stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(op)) );
    stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(dep1))) );
    stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(mkexpr(dep2))) );
 }
@@ -654,20 +701,9 @@ void setFlags_DEP1_DEP2 ( IROp op8, IRTemp dep1, IRTemp dep2, IRType ty )
 /* Set the OP and DEP1 fields only, and write zero to DEP2. */
 
 static 
-void setFlags_DEP1 ( IROp op8, IRTemp dep1, IRType ty )
+void setFlags_DEP1 ( IROp op, IRTemp dep1, IRType ty )
 {
-   Int ccOp = ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2);
-
-   vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
-
-   switch (op8) {
-      case Iop_Or8:
-      case Iop_And8:
-      case Iop_Xor8: ccOp += X86G_CC_OP_LOGICB; break;
-      default:       ppIROp(op8);
-                     vpanic("setFlags_DEP1(x86)");
-   }
-   stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(ccOp)) );
+   stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(op)) );
    stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(dep1))) );
    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0)) );
 }
@@ -677,32 +713,19 @@ void setFlags_DEP1 ( IROp op8, IRTemp dep1, IRType ty )
    result.  Except if the shift amount is zero, the thunk is left
    unchanged. */
 
-static void setFlags_DEP1_DEP2_shift ( IROp    op32,
+static void setFlags_DEP1_DEP2_shift ( IROp    op,
                                        IRTemp  res,
                                        IRTemp  resUS,
                                        IRType  ty,
                                        IRTemp  guard )
 {
-   Int ccOp = ty==Ity_I8 ? 2 : (ty==Ity_I16 ? 1 : 0);
-
-   vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
-   vassert(guard);
-
-   /* Both kinds of right shifts are handled by the same thunk
-      operation. */
-   switch (op32) {
-      case Iop_Shr32:
-      case Iop_Sar32: ccOp = X86G_CC_OP_SHRL - ccOp; break;
-      case Iop_Shl32: ccOp = X86G_CC_OP_SHLL - ccOp; break;
-      default:        ppIROp(op32);
-                      vpanic("setFlags_DEP1_DEP2_shift(x86)");
-   }
+    vassert(guard);
 
    /* DEP1 contains the result, DEP2 contains the undershifted value. */
    stmt( IRStmt_Put( OFFB_CC_OP,
                      IRExpr_Mux0X( mkexpr(guard),
                                    IRExpr_Get(OFFB_CC_OP,Ity_I32),
-                                   mkU32(ccOp))) );
+                                   mkU32(op))) );
    stmt( IRStmt_Put( OFFB_CC_DEP1,
                      IRExpr_Mux0X( mkexpr(guard),
                                    IRExpr_Get(OFFB_CC_DEP1,Ity_I32),
@@ -714,88 +737,85 @@ static void setFlags_DEP1_DEP2_shift ( IROp    op32,
 }
 
 
+
+
 /* For the inc/dec case, we store in DEP1 the result value and in NDEP
    the former value of the carry flag, which unfortunately we have to
    compute. */
-
+#if 0
 static void setFlags_INC_DEC ( Bool inc, IRTemp res, IRType ty )
 {
-   Int ccOp = inc ? X86G_CC_OP_INCB : X86G_CC_OP_DECB;
+   Int ccOp = inc ? ARMG_CC_OP_INC : ARMG_CC_OP_DEC;
+//   Int ccOp = inc ? X86G_CC_OP_INCB : X86G_CC_OP_DECB;
    
    ccOp += ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2);
    vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
 
    /* This has to come first, because calculating the C flag 
       may require reading all four thunk fields. */
-   stmt( IRStmt_Put( OFFB_CC_NDEP, mk_x86g_calculate_eflags_c()) );
+//   stmt( IRStmt_Put( OFFB_CC_NDEP, mk_armg_calculate_eflags_c()) );
    stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(ccOp)) );
    stmt( IRStmt_Put( OFFB_CC_DEP1, mkexpr(res)) );
    stmt( IRStmt_Put( OFFB_CC_DEP2, mkU32(0)) );
 }
+#endif
+
 
 
 /* Multiplies are pretty much like add and sub: DEP1 and DEP2 hold the
    two arguments. */
 
 static
-void setFlags_MUL ( IRType ty, IRTemp arg1, IRTemp arg2, UInt base_op )
-{
-   switch (ty) {
-      case Ity_I8:
-         stmt( IRStmt_Put( OFFB_CC_OP, mkU32(base_op+0) ) );
-         break;
-      case Ity_I16:
-         stmt( IRStmt_Put( OFFB_CC_OP, mkU32(base_op+1) ) );
-         break;
-      case Ity_I32:
-         stmt( IRStmt_Put( OFFB_CC_OP, mkU32(base_op+2) ) );
-         break;
-      default:
-         vpanic("setFlags_MUL(x86)");
-   }
-   stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(arg1)) ));
-   stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(mkexpr(arg2)) ));
+void setFlags_MUL ( IRTemp arg1, IRTemp arg2, UInt op )
+{
+    stmt( IRStmt_Put( OFFB_CC_OP, mkU32(op) ) );
+    stmt( IRStmt_Put( OFFB_CC_DEP1, widenUto32(mkexpr(arg1)) ));
+    stmt( IRStmt_Put( OFFB_CC_DEP2, widenUto32(mkexpr(arg2)) ));
 }
-#endif
+
+
+
+
+
+
+
+
 
 
 /* -------------- Condition codes. -------------- */
 
-/* Condition codes, using the Intel encoding.  */
+/* Condition codes, using the ARM encoding.  */
 
+// CAB: Just used for debugging printouts ?
 static Char* name_ARMCondcode ( ARMCondcode cond )
 {
    switch (cond) {
-// ToDo: rehash for ARM
-#if 0
-      case X86CondO:      return "o";
-      case X86CondNO:     return "no";
-      case X86CondB:      return "b";
-      case X86CondNB:     return "nb";
-      case X86CondZ:      return "z";
-      case X86CondNZ:     return "nz";
-      case X86CondBE:     return "be";
-      case X86CondNBE:    return "nbe";
-      case X86CondS:      return "s";
-      case X86CondNS:     return "ns";
-      case X86CondP:      return "p";
-      case X86CondNP:     return "np";
-      case X86CondL:      return "l";
-      case X86CondNL:     return "nl";
-      case X86CondLE:     return "le";
-      case X86CondNLE:    return "nle";
-#endif
-      default: vpanic("name_ARMCondcode");
+       case ARMCondEQ:    return "eq";
+       case ARMCondNE:    return "ne";
+       case ARMCondHS:    return "hs";
+       case ARMCondLO:    return "no";
+       case ARMCondMI:    return "mi";
+       case ARMCondPL:    return "pl";
+       case ARMCondVS:    return "vs";
+       case ARMCondVC:    return "vc";
+       case ARMCondHI:    return "hi";
+       case ARMCondLS:    return "ls";
+       case ARMCondGE:    return "ge";
+       case ARMCondLT:    return "lt";
+       case ARMCondGT:    return "gt";
+       case ARMCondLE:    return "le";
+       case ARMCondAL:    return "al";
+       case ARMCondNV:    return "nv";
+       default: vpanic("name_ARMCondcode");
    }
 }
 
-#if 0
-// TODO: probably useful for ARM too
+
 static 
-X86Condcode positiveIse_X86Condcode ( X86Condcode  cond,
+ARMCondcode positiveIse_ARMCondcode ( ARMCondcode  cond,
                                       Bool*     needInvert )
 {
-   vassert(cond >= X86CondO && cond <= X86CondNLE);
+   vassert(cond >= ARMCondEQ && cond <= ARMCondNV);
    if (cond & 1) {
       *needInvert = True;
       return cond-1;
@@ -804,7 +824,154 @@ X86Condcode positiveIse_X86Condcode ( X86Condcode  cond,
       return cond;
    }
 }
-#endif
+
+
+
+
+
+
+
+
+static
+IRTemp dis_shift_lsl ( UInt theInstr )
+{
+    IRTemp tmp = newTemp(Ity_I32);
+    UChar set_flags = (theInstr >> 20) & 1;
+    UChar is_imm_shft = (theInstr >> 4) & 1;
+    IRTemp Rm = newTemp(Ity_I32);
+    IRTemp Rs = newTemp(Ity_I32);
+    UInt Rs_0;
+    UInt imm;
+
+    assign(Rm, getIReg(theInstr & 0xF));
+    
+    if (is_imm_shft) {  // Immediate shift
+       imm = (theInstr >> 7) & 0x1F;
+       if ( imm == 0 ) {  // op = Rm, carry = C Flag;
+           return Rm;
+       }
+       else {             // op = Rm << imm, carry = Rm[32 - imm];
+           return Rm;
+       }
+    }
+    else {  // Register Shift
+       assign(Rs, getIReg((theInstr >> 8) & 0xF));
+       Rs_0 = Rs & 0xFF;   // Rs[7:0]
+       if ( Rs_0 == 0 ) {        // op = Rm, carry = C Flag;
+           return Rm;
+       }
+       else if ( Rs_0 < 32 ) {   // op = Rm LSL Rs, carry = Rm[32 - Rs]
+
+           // CAB: How to express LSL?
+
+           return 0;
+       }
+       else if ( Rs_0 == 32 ) {  // op = 0, carry = Rm[0];
+           return 0;
+       }
+       else {                    // op = 0, carry = 0;
+           return 0;
+       }
+    }
+
+//         setFlags_DEP1_DEP2( op, dep1, dep2 )
+//   stmt( IRStmt_Put( OFFB_CC_OP,   mkU32(thunkOp) ) );
+//    putIReg(r0, getIReg(r1));
+//    DIP("mov %i,%i\n", r0, r1);
+
+    
+    return 0;  /*notreached*/
+}
+
+
+
+/* Returns shifted result to a temp */
+static
+IRTemp dis_shift ( UInt theInstr )
+{
+    UChar shift_op = (theInstr >> 5) & 0xF;  // second byte
+
+    // CAB TODO: Check what can do with R15... strict limits apply (ARM A5-9)
+   
+    // We shouldn't have any 'op' with bits 4=1 and 7=1 : 1xx1
+    switch (shift_op) {
+    case 0x0:
+    case 0x8:
+    case 0x1: return dis_shift_lsl(theInstr);
+/*
+    case 0x2:
+    case 0xA:
+    case 0x3: return dis_shift_lsr(theInstr);
+
+    case 0x4:
+    case 0xC:
+    case 0x5: return dis_shift_asr(theInstr);
+
+    case 0x6:
+    case 0xE:
+    case 0x7: return dis_shift_ror(theInstr);  // Also RRX
+*/
+    default:
+       // Error: Any other value shouldn't be here.
+       vpanic("dis_shift(ARM)");
+       return 0; 
+    }
+}
+
+
+
+
+
+/* -------------- Helper for MOV. -------------- */
+/* MOV R2, R0            ; R2 = R0
+   MOV R2, R0, LSL #2    ; shift R0 left by 2, write to R2  (R2 = R0 x 4)
+   MOV R2, R4, ROR R3    ; R2 = R4 rotated right by val of R3
+
+   <opcode>{<cond>}{S}  <Rd>, <shifter_op>
+   where <shifter_op> => #imm | <Rm> | <Rm>, LSL <Rs> | ... See ARM ARM A5-2
+   (<Rn> not used)
+*/
+/*
+  if cond_passed(cond)
+    Rd = shifter_op
+    if S bit set
+      if Rd is R15
+        => Err.  This is undefined when executed in User/System mode.
+      else
+        N flag = Rd[31]                   (post shift if shift)
+        Z flag = if Rd ==0 the 1 else 0   (post shift if shift)
+        C flag = shifter_carry_out
+       V flag = unaffected.
+
+  => Flags dep on Rd, Rm, Rs!
+  ... mind you, that's more than one IR instruction... lsl + move... ?
+*/
+static
+void dis_mov_reg ( UInt theInstr )
+{
+    UChar S = (theInstr >> 20) & 1;
+//    UChar Rn = (theInstr >> 16) & 0xF;  // Not used
+    UChar Rd = (theInstr >> 12) & 0xF;
+    UChar Rm = theInstr & 0xF;
+    UChar Rs;
+    UInt shift_imm;
+    UChar reg_shft = (theInstr >> 4) & 1;
+    IRTemp t1;
+
+//    vex_printf("dis_move_reg\n");
+    
+    putIReg(Rd, mkexpr(dis_shift( theInstr )));
+
+    return;
+}
+
+
+
+
+
+
+
+
 
 
 /*------------------------------------------------------------*/
@@ -828,6 +995,7 @@ static DisResult disInstr ( /*IN*/  Bool    resteerOK,
    IRTemp    addr, t1, t2;
    Int       alen;
    UChar     opc, modrm, abyte;
+   ARMCondcode cond;
    UInt      d32;
    UChar     dis_buf[50];
    Int       am_sz, d_sz;
@@ -849,55 +1017,222 @@ static DisResult disInstr ( /*IN*/  Bool    resteerOK,
 
    theInstr = *(UInt*)(&guest_code[delta]);
 
+   vex_printf("START: 0x%x\n", theInstr );
+
    DIP("\t0x%x:  ", guest_pc_bbstart+delta);
 
-#if 0
+
+
    // TODO: fix the client-request stuff, else nothing will work
+
    /* Spot the client-request magic sequence. */
+   // Essentially a v. unlikely sequence of noops that we can catch
    {
       UChar* code = (UChar*)(guest_code + delta);
-      /* Spot this:
-         C1C01D                roll $29, %eax
-         C1C003                roll $3,  %eax
-         C1C81B                rorl $27, %eax
-         C1C805                rorl $5,  %eax
-         C1C00D                roll $13, %eax
-         C1C013                roll $19, %eax      
+      /* Spot this:                                // CAB: easy way to rotate left?
+         E1A00EE0                   mov  r0, r0, ror #29
+        E1A001E0                   mov  r0, r0, ror #3
+        E1A00DE0                   mov  r0, r0, ror #27
+        E1A002E0                   mov  r0, r0, ror #5
+        E1A006E0                   mov  r0, r0, ror #13
+        E1A009E0                   mov  r0, r0, ror #19
       */
-      if (code[ 0] == 0xC1 && code[ 1] == 0xC0 && code[ 2] == 0x1D &&
-          code[ 3] == 0xC1 && code[ 4] == 0xC0 && code[ 5] == 0x03 &&
-          code[ 6] == 0xC1 && code[ 7] == 0xC8 && code[ 8] == 0x1B &&
-          code[ 9] == 0xC1 && code[10] == 0xC8 && code[11] == 0x05 &&
-          code[12] == 0xC1 && code[13] == 0xC0 && code[14] == 0x0D &&
-          code[15] == 0xC1 && code[16] == 0xC0 && code[17] == 0x13
+      if (code[ 0] == 0xE1 && code[ 1] == 0xA0 && code[ 2] == 0x0E && code[ 3] == 0xE0 &&
+          code[ 4] == 0xE1 && code[ 5] == 0xA0 && code[ 6] == 0x01 && code[ 7] == 0xE0 &&
+          code[ 8] == 0xE1 && code[ 9] == 0xA0 && code[10] == 0x0D && code[11] == 0xE0 &&
+          code[12] == 0xE1 && code[13] == 0xA0 && code[14] == 0x02 && code[15] == 0xE0 &&
+          code[16] == 0xE1 && code[17] == 0xA0 && code[18] == 0x06 && code[19] == 0xE0 &&
+          code[20] == 0xE1 && code[21] == 0xA0 && code[22] == 0x09 && code[23] == 0xE0
          ) {
-         DIP("%%edx = client_request ( %%eax )\n");         
-         delta += 18;
-         jmp_lit(Ijk_ClientReq, guest_eip_bbstart+delta);
+         DIP("?CAB? = client_request ( ?CAB? )\n");
+
+         delta += 24;  // CAB: this right?  we're adding 24 UInts, rather than UChars...
+
+        // CAB: This right?
+//         jmp_lit(Ijk_ClientReq, guest_pc_bbstart+delta);
+        irbb->next     = mkU32(guest_pc_bbstart+delta);
+        irbb->jumpkind = Ijk_ClientReq;
+
          whatNext = Dis_StopHere;
          goto decode_success;
       }
    }
-#endif
+
+
+
+
+   /*
+     Deal with condition first
+    */
+   cond = (theInstr >> 28) & 0xF;    /* opcode: bits 31:28 */
+   switch (cond) {
+   case 0xF:   // => Illegal instruction prior to v5 (see ARM ARM A3-5)
+       vex_printf("disInstr(arm): illegal condition\n");
+       goto decode_failure;
+
+   case 0xE:   // => Unconditional: go translate the instruction
+       break;
+
+   default:    // => Valid condition: translate the condition test first
+       stmt( IRStmt_Exit( mk_armg_calculate_condition(cond),
+                         Ijk_Boring,
+                         IRConst_U32(guest_pc_bbstart+delta+4) ) );
+//       irbb->next     = mkU32(guest_pc_bbstart+delta+4);
+//       irbb->jumpkind = Ijk_Boring;
+   }
+   
+
+
+
+
+   /*
+     Deal with multiplies, load/store instructions
+     ARM ARM A3-3
+     ...
+    */
+
+   
+   /*
+     Deal with 'misc instructions'
+     ARM ARM A3-4
+     ...
+    */
+
+
+
+
 
    /* As per ARM ARM v2 page A3-2, primary opcode appears to be in
       bits 27:21 of the instruction (roughly).  Hence ... */
+   opc = (theInstr >> 21) & 0x7F;    /* opcode: bits 27:21 */
+
+   switch (opc) {
+
+       /* DPI: xxxx 000a aaaS nnnn dddd ...
+               cond [opcode ] op1  dest op2
+         24:21 => opcode
+         20    => (S)et flag (sets NZCV flags of CPSR: opcode dependant)
+         19:16 => Rn
+         15:12 => Rd
+       */
+       /* DPI, Register: operand2 => cccc cttt mmmm
+         11:7  => Rc (11:6, 7=0), or #c
+         6:4   => shift instr
+         3:0   => Rm
+       */
+       /* DPI, Immediate: operand2 => rrrr bbbb bbbb
+         19:16 => Rn
+         15:12 => Rd
+         11:8  => Rr
+         7:0   => Rb
+       */
+
+   case 0x00:            // AND   Boolean And           Rd = Rn AND Op2
+       goto decode_failure;
+   case 0x01:            // EOR   Boolean Eor           Rd = Rn EOR Op2
+       goto decode_failure;
+
+   case 0x02:            // SUB   Subtract              Rd = Rn  -  Op2
+       /*      e24cb004        sub     fp, ip, #4      ; 0x4
+              1110 0010 0100 1100 1011 0000 0000 0100
+       */
+       vex_printf("OPCODE: SUB\n");
+       goto decode_failure;
+
+   case 0x03:            // RSB   Reverse Subtract      Rd = Op2 -  Rn
+       goto decode_failure;
+   case 0x04:            // ADD   Addition              Rd = Rn  +  Op2
+       goto decode_failure;
+   case 0x05:            // ADC   Add with Carry        Rd = Rn  +  Op2 + C
+       goto decode_failure;
+   case 0x06:            // SBC   Subtract with carry   Rd = Rn  -  Op2 - (1-C)
+       goto decode_failure;
+   case 0x07:            // RSC   Reverse sub w/carry   Rd = Op2 -  Rn  - (1-C)
+       goto decode_failure;
+   case 0x08:            // TST   Test bit              Rn AND Op2
+       goto decode_failure;
+   case 0x09:            // TEQ   Test equality         Rn EOR Op2
+       goto decode_failure;
+   case 0x0A:            // CMP   Compare               Rn  -  Op2
+       goto decode_failure;
+   case 0x0B:            // CMN   Compare Negative      Rn  + Op2
+       goto decode_failure;
+   case 0x0C:            // ORR   Boolean Or            Rd = Rn OR  Op2
+       goto decode_failure;
+
+
+
+   case 0x0D:            // MOV (reg)
+       vex_printf("OPCODE: MOV(reg)\n");
+       dis_mov_reg(theInstr);
+       delta++;
+       break;
+
+
+   case 0x0E:            // BIC   Bit clear             Rd = Rn AND NOT Op2
+       goto decode_failure;
+   case 0x0F:            // MVN   Move Not              Rd =    NOT Op2
+       goto decode_failure;
+
+
+
+   case 0x1D:            // MOV (imm)
+       /*      e3a00014        mov     r0, #20 ; 0x14
+              1110 0011 1010 0000 0000 0000 0001 0100
+       */
+       vex_printf("OPCODE: MOV(imm)\n");
+       goto decode_failure;
+
+
+
+
+
+
+
+   case 0x49:     // STMDB: STM(1), decrement before
+       /* e92dd810        stmdb   sp!, {r4, fp, ip, lr, pc}
+          1110 1001 0010 1101 1101 1000 0001 0000
+          1110 100P U0W0 Rn   reg list
+          P=1 => Rn included in range of mem
+          U=0 => Rn lies at top of mem range
+          W=1 => Base reg updated after transfer (U=1 => incremented 4x num regs)
+          opc => 0100 1001 => 49
+        */
+       vex_printf("OPCODE: STM-DB\n");
+       goto decode_failure;
+
+
+       
+   case 0x58:
+   case 0x59:
+   case 0x5A:
+   case 0x5B:
+   case 0x5D:
+   case 0x5E:
+   case 0x5F:
+       /* BL
+         ebfffffe        bl      0 <newHHW>
+         1110 1011 1111 1111 1111 1111 1111 1110
+         cond 101L signed_immediate_24
+         L=1 => return address stored in link register (R14)
+         opcode => 101 1xxx => 0x58 to 0x5F
+       */
+       vex_printf("OPCODE: BL\n");
+       goto decode_failure;
+       
 
-   switch ((theInstr >> 20) & 0x7F) {
-
-   /* ------------------------ ??? ------------------------ */
-  
    default:
    decode_failure:
    /* All decode failures end up here. */
    vex_printf("disInstr(arm): unhandled instruction: "
-              "0x%x\n", theInstr );
+              "0x%x (opcode: 0x%x)\n", theInstr, opc );
    vpanic("armToIR: unimplemented insn");
 
    } /* switch (opc) for the main (primary) opcode switch. */
 
   decode_success:
    /* All decode successes end up here. */
+   vex_printf("disInstr(arm): success");
    DIP("\n");
 
    *size = 4;