- Mucho x86 to IR hacking.
- Build with Intel icc as it can warn about int-enum mismatches


git-svn-id: svn://svn.valgrind.org/vex/trunk@65 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/Makefile b/Makefile
index f841b13..0299a1e 100644
--- a/Makefile
+++ b/Makefile
@@ -27,8 +27,20 @@
 APP_OBJS =	test_main.o
 
 
-CC = gcc341
-CCFLAGS = -g -Wall -Wshadow
+#CC = gcc341
+#CCFLAGS = -g -Wall -Wshadow
+
+CC = icc
+CCFLAGS = -g  -Wbrief -Wall -wd981 -wd279 -wd1287 -wd869 \
+	  -wd810 -wd1419 -wd181 -wd111 -wd167
+# 981: operands are evaluated in unspecified order
+# 279: controlling expression is constant
+# 1287: invalid attribute for parameter
+# 869: parameter "..." was never referenced
+# 810: conversion from "int" to "Char={char}" may lose significant bits
+# 181: argument is incompatible with corresponding format string conversion
+# 111: statement is unreachable
+# 167: argument of type unsigned char incompatible with formal of type char
 
 all: libvex.a $(APP_OBJS)
 	$(CC) $(CCFLAGS) -o vex $(APP_OBJS) libvex.a
diff --git a/priv/guest-x86/x86guest_defs.h b/priv/guest-x86/x86guest_defs.h
index 7e25045..0660860 100644
--- a/priv/guest-x86/x86guest_defs.h
+++ b/priv/guest-x86/x86guest_defs.h
@@ -20,7 +20,7 @@
 /*---------------------------------------------------------*/
 
 extern
-IRBB* bbToIR_X86Instr ( Char*  x86code, 
+IRBB* bbToIR_X86Instr ( UChar* x86code, 
                         Addr64 eip, 
                         Int*   guest_bytes_read, 
                         Bool   (*byte_accessible)(Addr64),
diff --git a/priv/guest-x86/x86toIR.c b/priv/guest-x86/x86toIR.c
index e956eee..9ac4b84 100644
--- a/priv/guest-x86/x86toIR.c
+++ b/priv/guest-x86/x86toIR.c
@@ -177,29 +177,29 @@
 }
 
 /* Ditto, but write to a reg instead. */
-static IRStmt* putIReg ( Int sz, UInt archreg, IRExpr* e )
+static void putIReg ( Int sz, UInt archreg, IRExpr* e )
 {
    vassert(sz == 1 || sz == 2 || sz == 4);
    vassert(archreg < 8);
 
    vassert(!host_is_bigendian);
    vassert(sz == 4);
-   return IRStmt_Put(OFFB_EAX + 4*archreg, e);
+   stmt( IRStmt_Put(OFFB_EAX + 4*archreg, e) );
 }
 
-static IRStmt* assign ( IRTemp dst, IRExpr* e )
+static void assign ( IRTemp dst, IRExpr* e )
 {
-   return IRStmt_Tmp(dst, e);
+   stmt( IRStmt_Tmp(dst, e) );
 }
 
-static IRStmt* storeLE ( IRExpr* addr, IRExpr* data )
+static void storeLE ( IRExpr* addr, IRExpr* data )
 {
-   return IRStmt_STle(addr,data);
+   stmt( IRStmt_STle(addr,data) );
 }
 
-static IRStmt* copyToFrom ( IRTemp dst, IRTemp src )
+static void copyToFrom ( IRTemp dst, IRTemp src )
 {
-   return IRStmt_Tmp(dst, IRExpr_Tmp(src));
+   stmt( IRStmt_Tmp(dst, IRExpr_Tmp(src)) );
 }
 
 static IRExpr* binop ( IROp op, IRExpr* a1, IRExpr* a2 )
@@ -217,6 +217,65 @@
    return IRExpr_Const(IRConst_U32(i));
 }
 
+static IRExpr* mkU ( IRType ty, UInt i )
+{
+   if (ty == Ity_I8)  return IRExpr_Const(IRConst_U8(i));
+   if (ty == Ity_I16) return IRExpr_Const(IRConst_U16(i));
+   if (ty == Ity_I32) return IRExpr_Const(IRConst_U32(i));
+   vpanic("mkU(x86)");
+}
+
+static IRExpr* loadLE ( IRType ty, IRExpr* data )
+{
+   return IRExpr_LDle(ty,data);
+}
+
+static IROp mkSizedOp ( IRType ty, IROp op8 )
+{
+   vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
+   vassert(op8 == Iop_Add8 || op8 == Iop_Sub8 
+           || op8 == Iop_Adc8 || op8 == Iop_Sbb8 
+           || op8 == Iop_Mul8 
+           || op8 == Iop_Or8 || op8 == Iop_And8 || op8 == Iop_Xor8
+           || op8 == Iop_Shl8 || op8 == Iop_Shr8 || op8 == Iop_Sar8
+           || op8 == Iop_Not8 || op8 == Iop_Neg8 );
+   return (IROp)(
+             ((Int)op8) + (ty==Ity_I8 ? 0 : (ty==Ity_I16 ? 1 : 2))
+          );
+}
+
+static IRType szToTy ( Int n )
+{
+   switch (n) {
+      case 1: return Ity_I8;
+      case 2: return Ity_I16;
+      case 4: return Ity_I32;
+      default: vpanic("szToTy(x86)");
+   }
+}
+
+
+/*------------------------------------------------------------*/
+/*--- Helpers for %eflags.                                 ---*/
+/*------------------------------------------------------------*/
+
+static void setFlagsARITH ( IRTemp dstAfter,
+                            IRTemp src,
+                            IRTemp dstBefore,
+                            IRType ty,
+                            IROp   op8 )
+{
+   vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
+   switch (op8) {
+      case Iop_Sub8:
+         /* CC_SRC = %s, CC_DST = %d afterwards */
+
+      default: 
+         ppIROp(op8);
+         vpanic("setFlagsARITH(x86)");
+   }
+}
+
 
 //-- /*------------------------------------------------------------*/
 //-- /*--- CPU feature set stuff                                ---*/
@@ -480,15 +539,15 @@
 //-- }
 
 
-//-- 
-//-- static Char* nameGrp1 ( Int opc_aux )
-//-- {
-//--    static Char* grp1_names[8] 
-//--      = { "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp" };
-//--    if (opc_aux < 0 || opc_aux > 7) VG_(core_panic)("nameGrp1");
-//--    return grp1_names[opc_aux];
-//-- }
-//-- 
+
+static Char* nameGrp1 ( Int opc_aux )
+{
+   static Char* grp1_names[8] 
+     = { "add", "or", "adc", "sbb", "and", "sub", "xor", "cmp" };
+   if (opc_aux < 0 || opc_aux > 7) vpanic("nameGrp1(x86)");
+   return grp1_names[opc_aux];
+}
+
 //-- static Char* nameGrp2 ( Int opc_aux )
 //-- {
 //--    static Char* grp2_names[8] 
@@ -583,8 +642,7 @@
 //--    }
 //-- }
 
-static
-const Char nameISize ( Int size )
+static Char nameISize ( Int size )
 {
    switch (size) {
       case 4: return 'l';
@@ -792,6 +850,7 @@
          { UChar rm = mod_reg_rm;
            DIS(buf, "%s(%s)", sorbTxt(sorb), nameIReg(4,rm));
            *len = 1;
+	   vpanic("amode 1");
 	   return handleSegOverride(sorb, getIReg(4,rm));
          }
 
@@ -804,6 +863,7 @@
            UInt  d  = getSDisp8(delta);
            DIS(buf, "%s%d(%s)", sorbTxt(sorb), d, nameIReg(4,rm));
 	   *len = 2;
+	   vpanic("amode 2");
 	   return handleSegOverride(sorb,
                      binop(Iop_Add32,getIReg(4,rm),mkU32(d)));
          }
@@ -817,6 +877,7 @@
            UInt  d  = getUDisp32(delta);
            DIS(buf, "%s0x%x(%s)", sorbTxt(sorb), d, nameIReg(4,rm));
 	   *len = 5;
+	   vpanic("amode 3");
 	   return handleSegOverride(sorb,
                      binop(Iop_Add32,getIReg(4,rm),mkU32(d)));
          }
@@ -833,6 +894,7 @@
          { UInt d = getUDisp32(delta);
            *len = 5;
            DIS(buf, "%s(0x%x)", sorbTxt(sorb), d);
+	   vpanic("amode 4");
            return handleSegOverride(sorb, mkU32(d));
          }
 
@@ -866,6 +928,7 @@
             DIS(buf, "%s(%s,%s,%d)", sorbTxt(sorb), 
                       nameIReg(4,base_r), nameIReg(4,index_r), 1<<scale);
 	    *len = 2;
+	    vpanic("amode 5");
             return 
 	       handleSegOverride(sorb,
 	          binop(Iop_Add32, 
@@ -879,6 +942,7 @@
             DIS(buf, "%s0x%x(,%s,%d)", sorbTxt(sorb), d, 
                       nameIReg(4,index_r), 1<<scale);
             *len = 6;
+	    vpanic("amode 6");
             return
                handleSegOverride(sorb, 
 	          binop(Iop_Add32,
@@ -889,6 +953,7 @@
          if (index_r == R_ESP && base_r != R_EBP) {
             DIS(buf, "%s(%s,,)", sorbTxt(sorb), nameIReg(4,base_r));
 	    *len = 2;
+	    vpanic("amode 7");
 	    return handleSegOverride(sorb, getIReg(4,base_r));
          }
 
@@ -896,6 +961,7 @@
             UInt d = getUDisp32(delta);
             DIS(buf, "%s0x%x()", sorbTxt(sorb), d);
 	    *len = 6;
+	    vpanic("amode 8");
 	    return handleSegOverride(sorb, mkU32(d));
          }
 
@@ -921,12 +987,14 @@
          if (index_r == R_ESP) {
             DIS(buf, "%s%d(%s,,)", sorbTxt(sorb), d, nameIReg(4,base_r));
 	    *len = 3;
+	    vpanic("amode 9");
 	    return handleSegOverride(sorb, 
                       binop(Iop_Add32, getIReg(4,base_r), mkU32(d)) );
          } else {
             DIS(buf, "%s%d(%s,%s,%d)", sorbTxt(sorb), d, 
                      nameIReg(4,base_r), nameIReg(4,index_r), 1<<scale);
 	    *len = 3;
+	    vpanic("amode 10");
 	    return handleSegOverride(sorb,
                      binop(Iop_Add32,
 			   binop(Iop_Add32, 
@@ -956,12 +1024,14 @@
          if (index_r == R_ESP) {
             DIS(buf, "%s%d(%s,,)", sorbTxt(sorb), d, nameIReg(4,base_r));
 	    *len = 6;
+	    vpanic("amode 11");
 	    return handleSegOverride(sorb, 
                       binop(Iop_Add32, getIReg(4,base_r), mkU32(d)) );
          } else {
             DIS(buf, "%s%d(%s,%s,%d)", sorbTxt(sorb), d, 
                       nameIReg(4,base_r), nameIReg(4,index_r), 1<<scale);
 	    *len = 6;
+	    vpanic("amode 12");
 	    return handleSegOverride(sorb,
                      binop(Iop_Add32,
 			   binop(Iop_Add32, 
@@ -1326,7 +1396,7 @@
    //   UChar dis_buf[50];
 
    if (epartIsReg(rm)) {
-      stmt( putIReg(size, eregOfRM(rm), getIReg(size, gregOfRM(rm))) );
+      putIReg(size, eregOfRM(rm), getIReg(size, gregOfRM(rm)));
       DIP("mov%c %s,%s\n", nameISize(size), 
                            nameIReg(size,gregOfRM(rm)),
                            nameIReg(size,eregOfRM(rm)));
@@ -1470,79 +1540,71 @@
 //--    }
 //--    uInstr0(cb, CALLM_E, 0);
 //-- }
-//-- 
-//-- 
-//-- static 
-//-- Addr dis_Grp1 ( UCodeBlock* cb, 
-//--                 UChar       sorb,
-//--                 Addr eip, UChar modrm, 
-//--                 Int am_sz, Int d_sz, Int sz, UInt d32 )
-//-- {
-//--    Int   t1, t2, uopc;
-//--    UInt  pair;
-//--    UChar dis_buf[50];
-//--    if (epartIsReg(modrm)) {
-//--       vg_assert(am_sz == 1);
-//--       t1  = newTemp(cb);
-//--       uInstr2(cb, GET, sz, ArchReg, eregOfRM(modrm), TempReg, t1);
-//--       switch (gregOfRM(modrm)) {
-//--          case 0: uopc = ADD; break;  case 1: uopc = OR;  break;
-//--          case 2: uopc = ADC; break;  case 3: uopc = SBB; break;
-//--          case 4: uopc = AND; break;  case 5: uopc = SUB; break;
-//--          case 6: uopc = XOR; break;  case 7: uopc = SUB; break;
-//--          default: VG_(core_panic)("dis_Grp1(Reg): unhandled case");
-//--       }
-//--       if (uopc == AND || uopc == OR) {
-//--          Int tao = newTemp(cb);
-//--          uInstr2(cb, MOV, sz, Literal, 0, TempReg, tao);
-//--          uLiteral(cb, d32);
-//--          uInstr2(cb, uopc, sz, TempReg, tao, TempReg, t1);
-//--          setFlagsFromUOpcode(cb, uopc);
-//--       } else {
-//--          uInstr2(cb, uopc, sz, Literal, 0, TempReg, t1);
-//--          uLiteral(cb, d32);
-//--          setFlagsFromUOpcode(cb, uopc);
-//--       }
-//--       if (gregOfRM(modrm) < 7)
-//--          uInstr2(cb, PUT, sz, TempReg, t1, ArchReg, eregOfRM(modrm));
-//--       eip += (am_sz + d_sz);
-//--       DIP("%s%c $0x%x, %s\n", nameGrp1(gregOfRM(modrm)), nameISize(sz), d32, 
-//--                               nameIReg(sz,eregOfRM(modrm)));
-//--    } else {
-//--       pair = disAMode ( cb, sorb, eip, dis_buf);
-//--       t1   = LOW24(pair);
-//--       t2   = newTemp(cb);
-//--       eip  += HI8(pair);
-//--       eip  += d_sz;
-//--       uInstr2(cb, LOAD, sz, TempReg, t1, TempReg, t2);
-//--       switch (gregOfRM(modrm)) {
-//--          case 0: uopc = ADD; break;  case 1: uopc = OR;  break;
-//--          case 2: uopc = ADC; break;  case 3: uopc = SBB; break;
-//--          case 4: uopc = AND; break;  case 5: uopc = SUB; break;
-//--          case 6: uopc = XOR; break;  case 7: uopc = SUB; break;
-//--          default: VG_(core_panic)("dis_Grp1(Mem): unhandled case");
-//--       }
-//--       if (uopc == AND || uopc == OR) {
-//--          Int tao = newTemp(cb);
-//--          uInstr2(cb, MOV, sz, Literal, 0, TempReg, tao);
-//--          uLiteral(cb, d32);
-//--          uInstr2(cb, uopc, sz, TempReg, tao, TempReg, t2);
-//--          setFlagsFromUOpcode(cb, uopc);
-//--       } else {
-//--          uInstr2(cb, uopc, sz, Literal, 0, TempReg, t2);
-//--          uLiteral(cb, d32);
-//--          setFlagsFromUOpcode(cb, uopc);
-//--       }
-//--       if (gregOfRM(modrm) < 7) {
-//--          uInstr2(cb, STORE, sz, TempReg, t2, TempReg, t1);
-//--       }
-//--       DIP("%s%c $0x%x, %s\n", nameGrp1(gregOfRM(modrm)), nameISize(sz),
-//--                               d32, dis_buf);
-//--    }
-//--    return eip;
-//-- }
-//-- 
-//-- 
+
+
+static 
+UInt dis_Grp1 ( UChar       sorb,
+                UInt delta, UChar modrm, 
+                Int am_sz, Int d_sz, Int sz, UInt d32 )
+{
+   IRExpr* addr;
+   IRTemp  dst1, src, dst0;
+   IRType  ty;
+   IROp    uopc;
+   Int     len;
+   UChar   dis_buf[50];
+
+   ty = szToTy(sz);
+
+   switch (gregOfRM(modrm)) {
+      case 0: uopc = Iop_Add8; break;  case 1: uopc = Iop_Or8;  break;
+      case 2: uopc = Iop_Adc8; break;  case 3: uopc = Iop_Sbb8; break;
+      case 4: uopc = Iop_And8; break;  case 5: uopc = Iop_Sub8; break;
+      case 6: uopc = Iop_Xor8; break;  case 7: uopc = Iop_Sub8; break;
+      default: vpanic("dis_Grp1: unhandled case");
+   }
+   vassert(uopc != Iop_Adc8 && uopc != Iop_Sbb8);
+
+   dst0 = newTemp(ty);
+   dst1 = newTemp(ty);
+   src  = newTemp(ty);
+
+   if (epartIsReg(modrm)) {
+      vassert(am_sz == 1);
+
+      assign(dst0, getIReg(sz,eregOfRM(modrm)));
+      assign(src,  mkU(ty,d32));
+      assign(dst1, binop(mkSizedOp(ty,uopc), mkexpr(dst0), mkexpr(src)));
+
+      setFlagsARITH(dst1, dst0, src, ty, uopc);
+
+      if (gregOfRM(modrm) < 7)
+         putIReg(ty, eregOfRM(modrm), mkexpr(dst1));
+
+      delta += (am_sz + d_sz);
+      DIP("%s%c $0x%x, %s\n", nameGrp1(gregOfRM(modrm)), nameISize(sz), d32, 
+                              nameIReg(sz,eregOfRM(modrm)));
+   } else {
+      vassert(0==334);
+      addr  = disAMode ( &len, sorb, delta, dis_buf);
+
+      assign(dst0, loadLE(ty,addr));
+      assign(src, mkU(ty,d32));
+      assign(dst1, binop(mkSizedOp(ty,uopc), mkexpr(dst0), mkexpr(src)));
+
+      setFlagsARITH(dst1, dst0, src, ty, uopc);
+
+      if (gregOfRM(modrm) < 7)
+          storeLE(addr, mkexpr(dst1));
+
+      delta += (len+d_sz);
+      DIP("%s%c $0x%x, %s\n", nameGrp1(gregOfRM(modrm)), nameISize(sz),
+                              d32, dis_buf);
+   }
+   return delta;
+}
+
+
 //-- /* Group 2 extended opcodes. */
 //-- static
 //-- Addr dis_Grp2 ( UCodeBlock* cb, 
@@ -3924,7 +3986,7 @@
    UInt   d32 /*, pair*/;
    //   UChar  dis_buf[50];
    Int    am_sz, d_sz;
-   IRTemp t1, t2, t3, t4;
+   IRTemp t1, t2; //, t3, t4;
    IRType ty;
    //Char  loc_buf[M_VG_ERRTXT];
 
@@ -3945,7 +4007,8 @@
    IRStmt* first_stmt = last_stmt;
 
    *isEnd = False;
-   t1 = t2 = t3 = t4 = INVALID_IRTEMP;
+   t1 = t2 = INVALID_IRTEMP; 
+   //t3 = t4 = INVALID_IRTEMP;
 
    DIP("\t0x%x:  ", guest_eip+delta);
 
@@ -5358,9 +5421,9 @@
       {
          /* The normal sequence for a call. */
          t1 = newTemp(Ity_I32); 
-         stmt( assign(t1, binop(Iop_Sub32, getIReg(4,R_ESP), mkU32(4))) );
-         stmt( putIReg(4, R_ESP, mkexpr(t1)) );
-	 stmt( storeLE( mkexpr(t1), mkU32(guest_eip+delta)) );
+         assign(t1, binop(Iop_Sub32, getIReg(4,R_ESP), mkU32(4)));
+         putIReg(4, R_ESP, mkexpr(t1));
+	 storeLE( mkexpr(t1), mkU32(guest_eip+delta));
 	 jmp_lit(d32);
 	 //         LAST_UINSTR(cb).jmpkind = JmpCall;
          *isEnd = True;
@@ -6118,10 +6181,10 @@
       vassert(sz == 2 || sz == 4);
       ty = sz==2 ? Ity_I16 : Ity_I32;
       t1 = newTemp(ty); t2 = newTemp(ty);
-      stmt( assign(t1, getIReg(sz, opc-0x50)) );
-      stmt( assign(t2, binop(Iop_Sub32, getIReg(4, R_ESP), mkU32(sz))) );
-      stmt( putIReg(4, R_ESP, mkexpr(t2) ) );
-      stmt( storeLE(mkexpr(t2),mkexpr(t1)) );
+      assign(t1, getIReg(sz, opc-0x50));
+      assign(t2, binop(Iop_Sub32, getIReg(4, R_ESP), mkU32(sz)));
+      putIReg(4, R_ESP, mkexpr(t2) );
+      storeLE(mkexpr(t2),mkexpr(t1));
       DIP("push%c %s\n", nameISize(sz), nameIReg(sz,opc-0x50));
       break;
 
@@ -7417,7 +7480,7 @@
 /* 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_X86Instr ( Char*  x86code, 
+IRBB* bbToIR_X86Instr ( UChar* x86code, 
                         Addr64 eip, 
                         Int*   guest_bytes_read, 
                         Bool   (*byte_accessible)(Addr64),
diff --git a/priv/ir/ir_defs.c b/priv/ir/ir_defs.c
index 35d9409..caa6a0d 100644
--- a/priv/ir/ir_defs.c
+++ b/priv/ir/ir_defs.c
@@ -44,26 +44,48 @@
    if (tmp == INVALID_IRTEMP)
       vex_printf("INVALID_IRTEMP");
    else
-      vex_printf( "t%d", tmp);
+      vex_printf( "t%d", (Int)tmp);
 }
 
-
 void ppIROp ( IROp op )
 {
-  switch (op) {
-    case Iop_Add32: vex_printf( "Add32"); break;
-    case Iop_Sub32: vex_printf( "Sub32"); break;
-    case Iop_Mul32: vex_printf( "Mul32"); break;
-    case Iop_Or32:  vex_printf( "Or32");  break;
-    case Iop_And32: vex_printf( "And32"); break;
-    case Iop_Xor32: vex_printf( "Xor32"); break;
-    case Iop_Shl32: vex_printf( "Shl32"); break;
-    case Iop_Shr32: vex_printf( "Shr32"); break;
-    case Iop_Sar32: vex_printf( "Sar32"); break;
-    case Iop_Not32: vex_printf( "Not32"); break;
-    case Iop_Neg32: vex_printf( "Neg32"); break;
-    default: vpanic("ppIROp");
-  }
+   Char* str; 
+   IROp  base;
+   switch (op) {
+      case Iop_Add8 ... Iop_Add64:
+         str = "Add"; base = Iop_Add8; break;
+      case Iop_Sub8 ... Iop_Sub64:
+         str = "Sub"; base = Iop_Sub8; break;
+      case Iop_Mul8 ... Iop_Mul64:
+         str = "Mul"; base = Iop_Mul8; break;
+      case Iop_Or8 ... Iop_Or64:
+         str = "Or"; base = Iop_Or8; break;
+      case Iop_And8 ... Iop_And64:
+         str = "And"; base = Iop_And8; break;
+      case Iop_Xor8 ... Iop_Xor64:
+         str = "Xor"; base = Iop_Xor8; break;
+      case Iop_Shl8 ... Iop_Shl64:
+         str = "Shl"; base = Iop_Shl8; break;
+      case Iop_Shr8 ... Iop_Shr64:
+         str = "Shr"; base = Iop_Shr8; break;
+      case Iop_Sar8 ... Iop_Sar64:
+         str = "Sar"; base = Iop_Sar8; break;
+      case Iop_Neg8 ... Iop_Neg64:
+         str = "Neg"; base = Iop_Neg8; break;
+      case Iop_Not8 ... Iop_Not64:
+         str = "Not"; base = Iop_Not8; break;
+      /* other cases must explicitly "return;" */
+      default: 
+         vpanic("ppIROp(1)");
+   }
+  
+   switch (op - base) {
+      case 0: vex_printf(str); vex_printf("8"); break;
+      case 1: vex_printf(str); vex_printf("16"); break;
+      case 2: vex_printf(str); vex_printf("32"); break;
+      case 3: vex_printf(str); vex_printf("64"); break;
+      default: vpanic("ppIROp(2)");
+   }
 }
 
 void ppIRExpr ( IRExpr* e )
diff --git a/priv/main/vex_globals.c b/priv/main/vex_globals.c
index 0eac1eb..8407177 100644
--- a/priv/main/vex_globals.c
+++ b/priv/main/vex_globals.c
@@ -9,6 +9,7 @@
 #include "libvex_basictypes.h"
 
 #include "vex_util.h"
+#include "vex_globals.h"
 
 
 /* Global settings for the VEX library.  These are the
diff --git a/priv/main/vex_main.c b/priv/main/vex_main.c
index 52b4537..f889684 100644
--- a/priv/main/vex_main.c
+++ b/priv/main/vex_main.c
@@ -88,7 +88,7 @@
    void (*ppInstr) ( HInstr* );
    void (*ppReg) ( HReg );
    HInstrArray* (*iselBB) ( IRBB* );
-   IRBB* (*bbToIR) ( Char*, Addr64, Int*, Bool(*)(Addr64), Bool );
+   IRBB* (*bbToIR) ( UChar*, Addr64, Int*, Bool(*)(Addr64), Bool );
 
    Bool         host_is_bigendian = False;
    IRBB*        irbb;
diff --git a/priv/main/vex_util.c b/priv/main/vex_util.c
index 1c91ab8..73d70a6 100644
--- a/priv/main/vex_util.c
+++ b/priv/main/vex_util.c
@@ -7,6 +7,8 @@
 /*---------------------------------------------------------------*/
 
 #include "libvex_basictypes.h"
+#include "libvex.h"
+
 #include "vex_globals.h"
 #include "vex_util.h"
 
@@ -67,7 +69,8 @@
    storage_count_allocs_TOT += (ULong)storage_count_allocs;
    if (verb) {
       vex_printf("vex storage: total %lld (%lld), curr %d (%d)\n",
-	 	 storage_bytes_allocd_TOT, storage_count_allocs_TOT,
+	 	 (Long)storage_bytes_allocd_TOT, 
+                 (Long)storage_count_allocs_TOT,
 		 storage_bytes_allocd, storage_count_allocs );
    }
    storage_used = 0;
@@ -420,6 +423,36 @@
 }
 
 
+/* A general replacement for sprintf(). */
+
+static Char *vg_sprintf_ptr;
+
+static void add_to_vg_sprintf_buf ( Char c )
+{
+   *vg_sprintf_ptr++ = c;
+}
+
+UInt vex_sprintf ( Char* buf, const Char *format, ... )
+{
+   Int ret;
+   va_list vargs;
+
+   vg_sprintf_ptr = buf;
+
+   va_start(vargs,format);
+
+   ret = vprintf_wrk ( add_to_vg_sprintf_buf, format, vargs );
+   add_to_vg_sprintf_buf(0);
+
+   va_end(vargs);
+
+   vassert(vex_strlen(buf) == ret);
+   return ret;
+}
+
+
+
+
 /*---------------------------------------------------------------*/
 /*--- end                                          vex_util.c ---*/
 /*---------------------------------------------------------------*/
diff --git a/priv/main/vex_util.h b/priv/main/vex_util.h
index bb36f5a..97ffe9c 100644
--- a/priv/main/vex_util.h
+++ b/priv/main/vex_util.h
@@ -37,8 +37,10 @@
 /* Printing */
 
 __attribute__ ((format (printf, 1, 2)))
-extern UInt vex_printf ( const char *format, ... );
+extern UInt vex_printf ( const Char *format, ... );
 
+__attribute__ ((format (printf, 2, 3)))
+extern UInt vex_sprintf ( Char* buf, const Char *format, ... );
 
 #endif /* ndef __VEX_UTIL_H */
 
diff --git a/pub/libvex_ir.h b/pub/libvex_ir.h
index 3a6e604..9193675 100644
--- a/pub/libvex_ir.h
+++ b/pub/libvex_ir.h
@@ -63,18 +63,24 @@
 /* ------------------ Binary and unary ops ------------------ */
 
 typedef
-   enum { Iop_Add32, 
-          Iop_Sub32, 
-          Iop_Mul32, 
-          Iop_Or32, 
-          Iop_And32,
-          Iop_Xor32,
-          Iop_Shl32,
-          Iop_Shr32,
-          Iop_Sar32,
-          /* Tags for unary ops */
-          Iop_Not32,
-          Iop_Neg32
+   enum { 
+      /* Do not change this ordering.  The IR generators
+         rely on (eg) Iop_Add64 == IopAdd8 + 3. */
+      Iop_Add8,  Iop_Add16,  Iop_Add32,  Iop_Add64,
+      Iop_Sub8,  Iop_Sub16,  Iop_Sub32,  Iop_Sub64,
+      Iop_Adc8,  Iop_Adc16,  Iop_Adc32,  Iop_Adc64,
+      Iop_Sbb8,  Iop_Sbb16,  Iop_Sbb32,  Iop_Sbb64,
+      /* Signless mul.  MullS/MullU is elsewhere. */
+      Iop_Mul8,  Iop_Mul16,  Iop_Mul32,  Iop_Mul64,
+      Iop_Or8,   Iop_Or16,   Iop_Or32,   Iop_Or64,
+      Iop_And8,  Iop_And16,  Iop_And32,  Iop_And64,
+      Iop_Xor8,  Iop_Xor16,  Iop_Xor32,  Iop_Xor64,
+      Iop_Shl8,  Iop_Shl16,  Iop_Shl32,  Iop_Shl64,
+      Iop_Shr8,  Iop_Shr16,  Iop_Shr32,  Iop_Shr64,
+      Iop_Sar8,  Iop_Sar16,  Iop_Sar32,  Iop_Sar64,
+      /* Tags for unary ops */
+      Iop_Not8,  Iop_Not16,  Iop_Not32,  Iop_Not64,
+      Iop_Neg8,  Iop_Neg16,  Iop_Neg32,  Iop_Neg64
    }
    IROp;
 
diff --git a/test_main.c b/test_main.c
index 568333d..c3d0daa 100644
--- a/test_main.c
+++ b/test_main.c
@@ -19,25 +19,27 @@
 
 
 __attribute__ ((noreturn))
+static
 void failure_exit ( void )
 {
    fprintf(stdout, "VEX did failure_exit.  Bye.\n");
    exit(1);
 }
 
+static
 void log_bytes ( Char* bytes, Int nbytes )
 {
    fwrite ( bytes, 1, nbytes, stdout );
 }
 
 #define N_LINEBUF 10000
-Char linebuf[N_LINEBUF];
+static Char linebuf[N_LINEBUF];
 
 #define N_ORIGBUF 200
 #define N_TRANSBUF 1000
 
-UChar origbuf[N_ORIGBUF];
-UChar transbuf[N_TRANSBUF];
+static Char origbuf[N_ORIGBUF];
+static Char transbuf[N_TRANSBUF];
 
 
 int main ( int argc, char** argv )