]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Mucho instruction selector hacking.
authorJulian Seward <jseward@acm.org>
Sun, 18 Jul 2004 01:28:30 +0000 (01:28 +0000)
committerJulian Seward <jseward@acm.org>
Sun, 18 Jul 2004 01:28:30 +0000 (01:28 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@93

VEX/priv/guest-x86/x86toIR.c
VEX/priv/host-x86/isel_x86.c
VEX/priv/host-x86/x86h_defs.c
VEX/priv/host-x86/x86h_defs.h
VEX/priv/ir/ir_defs.c
VEX/pub/libvex_ir.h

index 249cefa2c53e40e609194e89c5f8c9e607e312f2..0e27cd401f0a178a1e40939504df92b3aa522302 100644 (file)
@@ -453,17 +453,17 @@ static void setFlags_DSTus_DST1 ( IROp    op8,
 
    /* CC_SRC = undershifted %d after, CC_DST = %d afterwards */
    stmt( IRStmt_Put( OFFB_CC_OP,
-                     IRExpr_Mux10( mkexpr(guard),
-                                   mkU32(ccOp),
-                                   IRExpr_Get(OFFB_CC_OP,Ity_I32))) );
+                     IRExpr_Mux0X( mkexpr(guard),
+                                   IRExpr_Get(OFFB_CC_OP,Ity_I32),
+                                   mkU32(ccOp))) );
    stmt( IRStmt_Put( OFFB_CC_SRC, 
-                     IRExpr_Mux10( mkexpr(guard),
-                                   widenUTo32(mkexpr(dstUS)),
-                                   IRExpr_Get(OFFB_CC_SRC,Ity_I32))) );
+                     IRExpr_Mux0X( mkexpr(guard),
+                                   IRExpr_Get(OFFB_CC_SRC,Ity_I32),
+                                   widenUTo32(mkexpr(dstUS)))) );
    stmt( IRStmt_Put( OFFB_CC_DST,
-                     IRExpr_Mux10( mkexpr(guard),
-                                   widenUTo32(mkexpr(dst1)),
-                                   IRExpr_Get(OFFB_CC_DST,Ity_I32))) );
+                     IRExpr_Mux0X( mkexpr(guard),
+                                   IRExpr_Get(OFFB_CC_DST,Ity_I32),
+                                   widenUTo32(mkexpr(dst1)))) );
 }
 
 
@@ -2030,7 +2030,7 @@ UInt dis_Grp2 ( UChar  sorb,
 
       IRTemp subshift  = newTemp(ty);
       IRTemp shift_amt = newTemp(Ity_I8);
-      IRTemp guard     = newTemp(Ity_Bit);
+      // IRTemp guard     = newTemp(Ity_Bit);
 
       switch (gregOfRM(modrm)) { 
          case 4: op8 = Iop_Shl8; break;
@@ -2054,11 +2054,11 @@ UInt dis_Grp2 ( UChar  sorb,
                                mkexpr(shift_amt), mkU8(1)),
                          mkU8(8*sz-1))));
       /* guard = (shift_amt != 0) */
-      assign(guard, binop(Iop_CmpNE8, 
-                           mkexpr(shift_amt), mkU8(0)));
+      //      assign(guard, binop(Iop_CmpNE8, 
+      //                     mkexpr(shift_amt), mkU8(0)));
 
       /* Build the flags thunk. */
-      setFlags_DSTus_DST1(op8, subshift, dst1, ty, guard);
+      setFlags_DSTus_DST1(op8, subshift, dst1, ty, shift_amt);
    } else {
       /* Rotate */
       vpanic("dis_Grp2: rotate");
@@ -3203,7 +3203,7 @@ UInt dis_SHLRD_Gv_Ev ( UChar sorb,
    IRTemp esrc     = newTemp(ty);
    IRTemp addr     = INVALID_IRTEMP;
    IRTemp tmpSH    = newTemp(Ity_I8);
-   IRTemp guard    = newTemp(Ity_Bit);
+   //   IRTemp guard    = newTemp(Ity_Bit);
    IRTemp tmpL     = INVALID_IRTEMP;
    IRTemp tmpRes   = INVALID_IRTEMP;
    IRTemp tmpSubSh = INVALID_IRTEMP;
@@ -3276,11 +3276,11 @@ UInt dis_SHLRD_Gv_Ev ( UChar sorb,
                       binop(Iop_And8, 
                             binop(Iop_Sub8, mkexpr(tmpSH), mkU8(1) ),
                             mask))) );
-   assign( guard, binop(Iop_CmpNE8, mkexpr(tmpSH), mkU8(0)) );
+   //assign( guard, binop(Iop_CmpNE8, mkexpr(tmpSH), mkU8(0)) );
 
    setFlags_DSTus_DST1 ( 
                        left_shift ? Iop_Shl8 : Iop_Sar8,
-                       tmpSubSh, tmpRes, ty, guard );
+                       tmpSubSh, tmpRes, ty, tmpSH );
 
    /* Put result back. */
 
index 776d1d4565b7fd7577a7daf30c178010f96f3e5a..24014a873eff26fe79b6fff6e413e744444fab3b 100644 (file)
@@ -93,7 +93,8 @@ static HReg newVRegI ( ISelEnv* env )
 /*---------------------------------------------------------*/
 
 /* forwards ... */
-static X86RMI* iselIntExpr_RMI ( ISelEnv* env, IRExpr* e );
+static X86RMI*   iselIntExpr_RMI   ( ISelEnv* env, IRExpr* e );
+static X86RM*    iselIntExpr_RM    ( ISelEnv* env, IRExpr* e );
 static X86AMode* iselIntExpr_AMode ( ISelEnv* env, IRExpr* e );
 
 
@@ -111,35 +112,50 @@ static X86Instr* mk_MOV_RR ( HReg src, HReg dst )
    there, and modify the copy.  The register allocator will do its
    best to map both vregs to the same real register, so the copies
    will often disappear later in the game.
+
+   This should handle expressions of 32, 16 and 8-bit type.  All
+   results are returned in a 32-bit register.  For 16- and 8-bit
+   expressions, the upper 16/24 bits are arbitrary, so you should
+   mask or sign extend partial values if necessary.
 */
 static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e )
 {
    vassert(e);
    IRType ty = typeOfIRExpr(env->type_env,e);
+   vassert(ty == Ity_I32 || Ity_I16 || Ity_I8);
 
    switch (e->tag) {
 
    case Iex_Tmp: {
-      vassert(ty == Ity_I32);
       return lookupIRTemp(env, e->Iex.Tmp.tmp);
    }
 
    case Iex_LDle: {
-      X86AMode* amode = iselIntExpr_AMode ( env, e->Iex.LDle.addr );
       HReg dst = newVRegI(env);
-      vassert(ty == Ity_I32);
-      addInstr(env, X86Instr_Alu32R(Xalu_MOV,
-                                   X86RMI_Mem(amode), dst) );
-      return dst;
+      X86AMode* amode = iselIntExpr_AMode ( env, e->Iex.LDle.addr );
+      if (ty == Ity_I32) {
+         addInstr(env, X86Instr_Alu32R(Xalu_MOV,
+                                       X86RMI_Mem(amode), dst) );
+         return dst;
+      }
+      if (ty == Ity_I16) {
+         addInstr(env, X86Instr_LoadEX(2,False,amode,dst));
+         return dst;
+      }
+      break;
    }
 
    case Iex_Binop: {
       X86AluOp   aluOp;
       X86ShiftOp shOp;
-      vassert(ty == Ity_I32);
+      /* Is it an addition or logical style op? */
       switch (e->Iex.Binop.op) {
          case Iop_Add32: aluOp = Xalu_ADD; break;
+
+         case Iop_Sub8: case Iop_Sub16:
          case Iop_Sub32: aluOp = Xalu_SUB; break;
+
+         case Iop_And8:
          case Iop_And32: aluOp = Xalu_AND; break;
          case Iop_Or32:  aluOp = Xalu_OR;  break;
          case Iop_Xor32: aluOp = Xalu_XOR; break;
@@ -155,6 +171,7 @@ static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e )
          addInstr(env, X86Instr_Alu32R(aluOp, rmi, dst));
          return dst;
       }
+      /* Perhaps a shift op? */
       switch (e->Iex.Binop.op) {
          case Iop_Shl32: shOp = Xsh_SHL; break;
          case Iop_Shr32: shOp = Xsh_SHR; break;
@@ -173,6 +190,22 @@ static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e )
       break;
    }
 
+   case Iex_Unop: {
+      switch (e->Iex.Unop.op) {
+         case Iop_8Uto32: {
+            HReg dst = newVRegI(env);
+            HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
+            addInstr(env, mk_MOV_RR(src,dst) );
+            addInstr(env, X86Instr_Alu32R(Xalu_AND,
+                                          X86RMI_Imm(0xFF), dst));
+            return dst;
+         }
+         default: 
+            break;
+      }
+      break;
+   }
+
    case Iex_Get: {
       if (ty == Ity_I32) {
          HReg dst = newVRegI(env);
@@ -183,6 +216,14 @@ static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e )
                           dst));
          return dst;
       }
+      if (ty == Ity_I8) {
+         HReg dst = newVRegI(env);
+         addInstr(env, X86Instr_LoadEX(
+                          1,False,
+                          X86AMode_IR(e->Iex.Get.offset,hregX86_EBP()),
+                          dst));
+         return dst;
+      }
       break;
    }
 
@@ -193,46 +234,54 @@ static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e )
       vassert(ty == Ity_I32);
       /* be very restrictive for now.  Only 32-bit ints allowed
          for args and return type. */
-     if (e->Iex.CCall.retty != Ity_I32)
-        break;
+      if (e->Iex.CCall.retty != Ity_I32)
+         break;
       /* push args on the stack, right to left. */
-     nargs = 0;
-     while (e->Iex.CCall.args[nargs]) nargs++;
-     for (i = nargs-1; i >= 0; i--) {
-        arg = e->Iex.CCall.args[i];
-        if (typeOfIRExpr(env->type_env,arg) != Ity_I32)
-           goto irreducible;
-        addInstr(env, X86Instr_Push(iselIntExpr_RMI(env, arg)));
-     }
-     target = 0x12345678; //FIND_HELPER(e->Iex.CCall.name);
-     addInstr(env, X86Instr_Alu32R(
-                                  Xalu_MOV,
-                                  X86RMI_Imm(target),
-                                  hregX86_EAX()));
-     addInstr(env, X86Instr_Call(hregX86_EAX()));
-     if (nargs > 0)
-       addInstr(env, X86Instr_Alu32R(Xalu_ADD,
-                                    X86RMI_Imm(4*nargs),
-                                    hregX86_ESP()));
-
-     return hregX86_EAX();
+      nargs = 0;
+      while (e->Iex.CCall.args[nargs]) nargs++;
+      for (i = nargs-1; i >= 0; i--) {
+         arg = e->Iex.CCall.args[i];
+         if (typeOfIRExpr(env->type_env,arg) != Ity_I32)
+            goto irreducible;
+         addInstr(env, X86Instr_Push(iselIntExpr_RMI(env, arg)));
+      }
+      target = 0x12345678; //FIND_HELPER(e->Iex.CCall.name);
+      addInstr(env, X86Instr_Alu32R(
+                       Xalu_MOV,
+                       X86RMI_Imm(target),
+                       hregX86_EAX()));
+      addInstr(env, X86Instr_Call(hregX86_EAX()));
+      if (nargs > 0)
+         addInstr(env, X86Instr_Alu32R(Xalu_ADD,
+                          X86RMI_Imm(4*nargs),
+                          hregX86_ESP()));
+      return hregX86_EAX();
    }
 
    /* 32/16/8-bit literals */
    case Iex_Const: {
-      UInt u;
-      vassert(ty == Ity_I32 || ty == Ity_I8);
-      switch (e->Iex.Const.con->tag) {
-         case Ico_U32: u = e->Iex.Const.con->Ico.U32; break;
-         case Ico_U16: u = 0xFFFF & (e->Iex.Const.con->Ico.U16); break;
-         case Ico_U8:  u = 0xFF   & (e->Iex.Const.con->Ico.U8); break;
-         default: vpanic("iselIntExpr_R.Iex_Const(x86h)");
-      }
-      HReg r = newVRegI(env);
-      addInstr(env, X86Instr_Alu32R(Xalu_MOV, X86RMI_Imm(u), r));
+      X86RMI* rmi = iselIntExpr_RMI ( env, e );
+      HReg    r   = newVRegI(env);
+      addInstr(env, X86Instr_Alu32R(Xalu_MOV, rmi, r));
       return r;
    }
 
+   case Iex_Mux0X: {
+      if (ty == Ity_I32 
+         && typeOfIRExpr(env->type_env,e->Iex.Mux0X.cond) == Ity_I8) {
+       HReg rX   = iselIntExpr_R(env, e->Iex.Mux0X.exprX);
+       X86RM* r0 = iselIntExpr_RM(env, e->Iex.Mux0X.expr0);
+       HReg dst = newVRegI(env);
+       addInstr(env, mk_MOV_RR(rX,dst));
+       HReg r8 = iselIntExpr_R(env, e->Iex.Mux0X.cond);
+       addInstr(env, X86Instr_Alu32R(Xalu_TEST,
+                                     X86RMI_Imm(0xFF), r8));
+       addInstr(env, X86Instr_CMovZ(r0,dst));
+       return dst;
+      }
+      break;
+   }
+
    default: 
    break;
    } /* switch (e->tag) */
@@ -250,12 +299,13 @@ static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e )
 
 /* Return an AMode which computes the value of the specified
    expression, possibly also adding insns to the code list as a
-   result.  
+   result.  The expression may only be a 32-bit one.
 */
 static X86AMode* iselIntExpr_AMode ( ISelEnv* env, IRExpr* e )
 {
    vassert(e);
-   vassert(typeOfIRExpr(env->type_env,e) == Ity_I32);
+   IRType ty = typeOfIRExpr(env->type_env,e);
+   vassert(ty == Ity_I32);
 
    /* Add32(expr1, Shl32(expr2, imm)) */
    if (e->tag == Iex_Binop
@@ -290,21 +340,29 @@ static X86AMode* iselIntExpr_AMode ( ISelEnv* env, IRExpr* e )
 }
 
 
-/* Similarly, calculate an expression into an X86RMI operand. */
+/* Similarly, calculate an expression into an X86RMI operand.  As with
+   iselIntExpr_R, the expression can have type 32, 16 or 8 bits.  */
 
 static X86RMI* iselIntExpr_RMI ( ISelEnv* env, IRExpr* e )
 {
    vassert(e);
-   vassert(typeOfIRExpr(env->type_env,e) == Ity_I32);
+   IRType ty = typeOfIRExpr(env->type_env,e);
+   vassert(ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8);
 
    /* special case: immediate */
-   if (e->tag == Iex_Const 
-       && e->Iex.Const.con->tag == Ico_U32) {
-      return X86RMI_Imm(e->Iex.Const.con->Ico.U32);
+   if (e->tag == Iex_Const) {
+      UInt u;
+      switch (e->Iex.Const.con->tag) {
+         case Ico_U32: u = e->Iex.Const.con->Ico.U32; break;
+         case Ico_U16: u = 0xFFFF & (e->Iex.Const.con->Ico.U16); break;
+         case Ico_U8:  u = 0xFF   & (e->Iex.Const.con->Ico.U8); break;
+         default: vpanic("iselIntExpr_RMI.Iex_Const(x86h)");
+      }
+      return X86RMI_Imm(u);
    }
 
    /* special case: 32-bit GET */
-   if (e->tag == Iex_Get && e->Iex.Get.ty ==Ity_I32) {
+   if (e->tag == Iex_Get && ty == Ity_I32) {
       return X86RMI_Mem(X86AMode_IR(e->Iex.Get.offset,
                                     hregX86_EBP()));
    }
@@ -319,17 +377,25 @@ static X86RMI* iselIntExpr_RMI ( ISelEnv* env, IRExpr* e )
 }
 
 
-/* Calculate an expression into an X86RI operand. */
+/* Calculate an expression into an X86RI operand.  As with
+   iselIntExpr_R, the expression can have type 32, 16 or 8 bits. */
 
 static X86RI* iselIntExpr_RI ( ISelEnv* env, IRExpr* e )
 {
    vassert(e);
-   vassert(typeOfIRExpr(env->type_env,e) == Ity_I32);
+   IRType ty = typeOfIRExpr(env->type_env,e);
+   vassert(ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8);
 
    /* special case: immediate */
-   if (e->tag == Iex_Const 
-       && e->Iex.Const.con->tag == Ico_U32) {
-      return X86RI_Imm(e->Iex.Const.con->Ico.U32);
+   if (e->tag == Iex_Const) {
+      UInt u;
+      switch (e->Iex.Const.con->tag) {
+         case Ico_U32: u = e->Iex.Const.con->Ico.U32; break;
+         case Ico_U16: u = 0xFFFF & (e->Iex.Const.con->Ico.U16); break;
+         case Ico_U8:  u = 0xFF   & (e->Iex.Const.con->Ico.U8); break;
+         default: vpanic("iselIntExpr_RMI.Iex_Const(x86h)");
+      }
+      return X86RI_Imm(u);
    }
 
    /* default case: calculate into a register and return that */
@@ -340,6 +406,32 @@ static X86RI* iselIntExpr_RI ( ISelEnv* env, IRExpr* e )
 }
 
 
+/* Similarly, calculate an expression into an X86RM operand.  As with
+   iselIntExpr_R, the expression can have type 32, 16 or 8 bits.  */
+
+static X86RM* iselIntExpr_RM ( ISelEnv* env, IRExpr* e )
+{
+   vassert(e);
+   IRType ty = typeOfIRExpr(env->type_env,e);
+   vassert(ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8);
+
+   /* special case: 32-bit GET */
+   if (e->tag == Iex_Get && ty == Ity_I32) {
+      return X86RM_Mem(X86AMode_IR(e->Iex.Get.offset,
+                                   hregX86_EBP()));
+   }
+
+   /* special case: load from memory */
+
+   /* default case: calculate into a register and return that */
+   {
+      HReg r = iselIntExpr_R ( env, e );
+      return X86RM_Reg(r);
+   }
+}
+
+
+
 /*---------------------------------------------------------*/
 /*--- ISEL: Statements                                  ---*/
 /*---------------------------------------------------------*/
@@ -385,7 +477,7 @@ static void iselStmt ( ISelEnv* env, IRStmt* stmt )
    case Ist_Tmp: {
       IRTemp tmp = stmt->Ist.Tmp.tmp;
       IRType ty = lookupIRTypeEnv(env->type_env, tmp);
-      if (ty == Ity_I32) {
+      if (ty == Ity_I32 || ty == Ity_I16 || ty == Ity_I8) {
          X86RMI* rmi = iselIntExpr_RMI(env, stmt->Ist.Tmp.expr);
          HReg dst = lookupIRTemp(env, tmp);
          addInstr(env, X86Instr_Alu32R(Xalu_MOV,rmi,dst));
@@ -471,6 +563,7 @@ HInstrArray* iselBB_X86 ( IRBB* bb )
       switch (bb->tyenv->types[i]) {
          case Ity_Bit:
          case Ity_I8:
+         case Ity_I16:
          case Ity_I32: hreg   = mkHReg(i, HRcInt, True); break;
          case Ity_I64: hreg   = mkHReg(i, HRcInt, True);
                        hregHI = mkHReg(i, HRcInt, True); break;
index 0a57fea818343b17b2b98ff7bdd0fddcec5df5ba..e5fb70dce59fec51c26163cb3406f71f3eb64b5d 100644 (file)
@@ -334,14 +334,16 @@ static void mapRegs_X86RM ( HRegRemap* m, X86RM* op )
 void ppX86AluOp ( X86AluOp op ) {
    Char* name;
    switch (op) {
-      case Xalu_MOV: name = "mov"; break;
-      case Xalu_ADD: name = "add"; break;
-      case Xalu_SUB: name = "sub"; break;
-      case Xalu_ADC: name = "adc"; break;
-      case Xalu_SBB: name = "sbb"; break;
-      case Xalu_AND: name = "and"; break;
-      case Xalu_OR:  name = "or";  break;
-      case Xalu_XOR: name = "xor"; break;
+      case Xalu_MOV:  name = "mov"; break;
+      case Xalu_CMP:  name = "cmp"; break;
+      case Xalu_TEST: name = "test"; break;
+      case Xalu_ADD:  name = "add"; break;
+      case Xalu_SUB:  name = "sub"; break;
+      case Xalu_ADC:  name = "adc"; break;
+      case Xalu_SBB:  name = "sbb"; break;
+      case Xalu_AND:  name = "and"; break;
+      case Xalu_OR:   name = "or";  break;
+      case Xalu_XOR:  name = "xor"; break;
       default: vpanic("ppX86AluOp");
    }
    vex_printf("%s", name);
@@ -409,6 +411,27 @@ X86Instr* X86Instr_GotoNZ ( Bool onlyWhenNZ, X86RI* dst ) {
    return i;
 }
 
+X86Instr* X86Instr_CMovZ  ( X86RM* src, HReg dst ) {
+   X86Instr* i      = LibVEX_Alloc(sizeof(X86Instr));
+   i->tag           = Xin_CMovZ;
+   i->Xin.CMovZ.src = src;
+   i->Xin.CMovZ.dst = dst;
+   return i;
+}
+
+X86Instr* X86Instr_LoadEX ( UChar szSmall, Bool syned,
+                            X86AMode* src, HReg dst ) {
+   X86Instr* i           = LibVEX_Alloc(sizeof(X86Instr));
+   i->tag                = Xin_LoadEX;
+   i->Xin.LoadEX.szSmall = szSmall;
+   i->Xin.LoadEX.syned   = syned;
+   i->Xin.LoadEX.src     = src;
+   i->Xin.LoadEX.dst     = dst;
+   vassert(szSmall == 1 || szSmall == 2);
+   return i;
+}
+
+
 void ppX86Instr ( X86Instr* i ) {
    switch (i->tag) {
       case Xin_Alu32R:
@@ -453,6 +476,20 @@ void ppX86Instr ( X86Instr* i ) {
             vex_printf(",%%eax ; ret");
          }
          return;
+      case Xin_CMovZ:
+         vex_printf("cmovz ");
+         ppX86RM(i->Xin.CMovZ.src);
+         vex_printf(",");
+         ppHRegX86(i->Xin.CMovZ.dst);
+         return;
+      case Xin_LoadEX:
+         vex_printf("mov%c%cl ",
+                    i->Xin.LoadEX.syned ? 's' : 'z',
+                    i->Xin.LoadEX.szSmall==1 ? 'b' : 'w');
+         ppX86AMode(i->Xin.LoadEX.src);
+         vex_printf(",");
+         ppHRegX86(i->Xin.LoadEX.dst);
+         return;
       default:
          vpanic("ppX86Instr");
    }
@@ -466,10 +503,16 @@ void getRegUsage_X86Instr (HRegUsage* u, X86Instr* i)
    switch (i->tag) {
       case Xin_Alu32R:
          addRegUsage_X86RMI(u, i->Xin.Alu32R.src);
-         if (i->Xin.Alu32R.op == Xalu_MOV)
+         if (i->Xin.Alu32R.op == Xalu_MOV) {
             addHRegUse(u, HRmWrite,  i->Xin.Alu32R.dst);
-         else
-            addHRegUse(u, HRmModify, i->Xin.Alu32R.dst);
+            return;
+         }
+         if (i->Xin.Alu32R.op == Xalu_CMP 
+             || i->Xin.Alu32R.op == Xalu_TEST) {
+            addHRegUse(u, HRmRead,  i->Xin.Alu32R.dst);
+            return;
+         }
+         addHRegUse(u, HRmModify, i->Xin.Alu32R.dst);
          return;
       case Xin_Alu32M:
          addRegUsage_X86RI(u, i->Xin.Alu32M.src);
index 8f922fb673716ec01bcfb8abb3cd68064a4f75bc..9bc4901edc4a3de59b40a1fb686903e1d675651f 100644 (file)
@@ -163,6 +163,8 @@ typedef
    enum {
       Xalu_INVALID,
       Xalu_MOV,
+      Xalu_CMP,
+      Xalu_TEST,
       Xalu_ADD, Xalu_SUB, Xalu_ADC, Xalu_SBB, 
       Xalu_AND, Xalu_OR, Xalu_XOR 
    }
@@ -191,7 +193,9 @@ typedef
       Xin_Sh32,      /* 32-bit shift/rotate, dst=REG or MEM */
       Xin_Push,      /* push (32-bit?) value on stack */
       Xin_Call,      /* call to address in register */
-      Xin_GotoNZ     /* conditional/unconditional jmp to dst */
+      Xin_GotoNZ,    /* conditional/unconditional jmp to dst */
+      Xin_CMovZ,     /* conditional move when Z flag set */
+      Xin_LoadEX     /* mov{s,z}{b,w}l from mem to reg */
    }
    X86InstrTag;
 
@@ -228,6 +232,19 @@ typedef
             Bool   onlyWhenNZ;
             X86RI* dst;
          } GotoNZ;
+         /* Mov src to dst (both 32-bit regs?) when the Z flag is
+            set. */
+         struct {
+            X86RM* src;
+            HReg   dst;
+         } CMovZ;
+         /* Sign/Zero extending loads.  Dst size is always 32 bits. */
+         struct {
+            UChar     szSmall;
+            Bool      syned;
+            X86AMode* src;
+            HReg      dst;
+         } LoadEX;
       } Xin;
    }
    X86Instr;
@@ -238,6 +255,10 @@ extern X86Instr* X86Instr_Sh32   ( X86ShiftOp, UInt, X86RM* );
 extern X86Instr* X86Instr_Push   ( X86RMI* );
 extern X86Instr* X86Instr_Call   ( HReg );
 extern X86Instr* X86Instr_GotoNZ ( Bool onlyWhenNZ, X86RI* dst );
+extern X86Instr* X86Instr_CMovZ  ( X86RM* src, HReg dst );
+extern X86Instr* X86Instr_LoadEX ( UChar szSmall, Bool syned,
+                                   X86AMode* src, HReg dst );
+
 
 extern void ppX86Instr ( X86Instr* );
 
index 658f996e259ffbb1311ee4f98acb3823f5f86eee..69129a1049afaf7bafbe010ea083bc70c91f5d90 100644 (file)
@@ -162,13 +162,13 @@ void ppIRExpr ( IRExpr* e )
       vex_printf("):");
       ppIRType(e->Iex.CCall.retty);
       break;
-    case Iex_Mux10:
-      vex_printf("Mux10(");
-      ppIRExpr(e->Iex.Mux10.cond);
+    case Iex_Mux0X:
+      vex_printf("Mux0X(");
+      ppIRExpr(e->Iex.Mux0X.cond);
       vex_printf(",");
-      ppIRExpr(e->Iex.Mux10.expr1);
+      ppIRExpr(e->Iex.Mux0X.expr0);
       vex_printf(",");
-      ppIRExpr(e->Iex.Mux10.expr0);
+      ppIRExpr(e->Iex.Mux0X.exprX);
       vex_printf(")");
       break;
     default:
@@ -343,12 +343,12 @@ IRExpr* IRExpr_CCall ( Char* name, IRType retty, IRExpr** args ) {
    e->Iex.CCall.args  = args;
    return e;
 }
-IRExpr* IRExpr_Mux10 ( IRExpr* cond, IRExpr* expr1, IRExpr* expr0 ) {
+IRExpr* IRExpr_Mux0X ( IRExpr* cond, IRExpr* expr0, IRExpr* exprX ) {
    IRExpr* e          = LibVEX_Alloc(sizeof(IRExpr));
-   e->tag             = Iex_Mux10;
-   e->Iex.Mux10.cond  = cond;
-   e->Iex.Mux10.expr1 = expr1;
-   e->Iex.Mux10.expr0 = expr0;
+   e->tag             = Iex_Mux0X;
+   e->Iex.Mux0X.cond  = cond;
+   e->Iex.Mux0X.expr0 = expr0;
+   e->Iex.Mux0X.exprX = exprX;
    return e;
 }
 
@@ -564,8 +564,8 @@ IRType typeOfIRExpr ( IRTypeEnv* tyenv, IRExpr* e )
          return t_dst;
       case Iex_CCall:
          return e->Iex.CCall.retty;
-      case Iex_Mux10:
-         return typeOfIRExpr(tyenv, e->Iex.Mux10.expr1);
+      case Iex_Mux0X:
+         return typeOfIRExpr(tyenv, e->Iex.Mux0X.expr0);
       default:
          ppIRExpr(e);
          vpanic("typeOfIRExpr");
@@ -646,10 +646,10 @@ void useBeforeDef_Expr ( IRBB* bb, IRStmt* stmt, IRExpr* expr, Int* def_counts )
          for (i = 0; expr->Iex.CCall.args[i]; i++)
             useBeforeDef_Expr(bb,stmt,expr->Iex.CCall.args[i],def_counts);
          break;
-      case Iex_Mux10:
-         useBeforeDef_Expr(bb,stmt,expr->Iex.Mux10.cond,def_counts);
-         useBeforeDef_Expr(bb,stmt,expr->Iex.Mux10.expr1,def_counts);
-         useBeforeDef_Expr(bb,stmt,expr->Iex.Mux10.expr0,def_counts);
+      case Iex_Mux0X:
+         useBeforeDef_Expr(bb,stmt,expr->Iex.Mux0X.cond,def_counts);
+         useBeforeDef_Expr(bb,stmt,expr->Iex.Mux0X.expr0,def_counts);
+         useBeforeDef_Expr(bb,stmt,expr->Iex.Mux0X.exprX,def_counts);
          break;
       default:
          vpanic("useBeforeDef_Expr");
@@ -742,15 +742,15 @@ void tcExpr ( IRBB* bb, IRStmt* stmt, IRExpr* expr, IRType gWordTy )
          break;
       case Iex_Const:
          break;
-      case Iex_Mux10:
-         tcExpr(bb,stmt, expr->Iex.Mux10.cond, gWordTy);
-         tcExpr(bb,stmt, expr->Iex.Mux10.expr1, gWordTy);
-         tcExpr(bb,stmt, expr->Iex.Mux10.expr0, gWordTy);
-         if (typeOfIRExpr(tyenv, expr->Iex.Mux10.cond) != Ity_Bit)
-            sanityCheckFail(bb,stmt,"Iex.Mux10.cond: cond :: Ity_Bit");
-         if (typeOfIRExpr(tyenv, expr->Iex.Mux10.expr1)
-             != typeOfIRExpr(tyenv, expr->Iex.Mux10.expr0))
-            sanityCheckFail(bb,stmt,"Iex.Mux10: expr1/expr0 mismatch");
+      case Iex_Mux0X:
+         tcExpr(bb,stmt, expr->Iex.Mux0X.cond, gWordTy);
+         tcExpr(bb,stmt, expr->Iex.Mux0X.expr0, gWordTy);
+         tcExpr(bb,stmt, expr->Iex.Mux0X.exprX, gWordTy);
+         if (typeOfIRExpr(tyenv, expr->Iex.Mux0X.cond) != Ity_I8)
+            sanityCheckFail(bb,stmt,"Iex.Mux0X.cond: cond :: Ity_I8");
+         if (typeOfIRExpr(tyenv, expr->Iex.Mux0X.expr0)
+             != typeOfIRExpr(tyenv, expr->Iex.Mux0X.exprX))
+            sanityCheckFail(bb,stmt,"Iex.Mux0X: expr0/exprX mismatch");
          break;
        default: 
          vpanic("tcExpr");
index 51901d4fe15343f7ab20c427c1e84f4b060b74db..e8bc2137e7c9b3a01c8a4a607a5ed7e0594db9b2 100644 (file)
@@ -72,8 +72,6 @@ typedef
       Iop_INVALID=0x13000,
       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,
@@ -124,7 +122,7 @@ data Expr
 */
 typedef
    enum { Iex_Get, Iex_Tmp, Iex_Binop, Iex_Unop, Iex_LDle, 
-          Iex_Const, Iex_CCall, Iex_Mux10 }
+          Iex_Const, Iex_CCall, Iex_Mux0X }
    IRExprTag;
 
 typedef 
@@ -161,9 +159,9 @@ typedef
          }  CCall;
          struct {
             struct _IRExpr* cond;
-            struct _IRExpr* expr1;
             struct _IRExpr* expr0;
-         } Mux10;
+            struct _IRExpr* exprX;
+         } Mux0X;
       } Iex;
    }
    IRExpr;
@@ -175,7 +173,7 @@ extern IRExpr* IRExpr_Unop  ( IROp op, IRExpr* arg );
 extern IRExpr* IRExpr_LDle  ( IRType ty, IRExpr* addr );
 extern IRExpr* IRExpr_Const ( IRConst* con );
 extern IRExpr* IRExpr_CCall ( Char* name, IRType retty, IRExpr** args );
-extern IRExpr* IRExpr_Mux10 ( IRExpr* cond, IRExpr* expr1, IRExpr* expr0 );
+extern IRExpr* IRExpr_Mux0X ( IRExpr* cond, IRExpr* expr0, IRExpr* exprX );
 
 extern void ppIRExpr ( IRExpr* );