]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
x86toIR: some multiply stuff
authorJulian Seward <jseward@acm.org>
Tue, 13 Jul 2004 18:42:17 +0000 (18:42 +0000)
committerJulian Seward <jseward@acm.org>
Tue, 13 Jul 2004 18:42:17 +0000 (18:42 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@79

VEX/priv/guest-x86/x86guest_defs.h
VEX/priv/guest-x86/x86toIR.c
VEX/priv/ir/ir_defs.c
VEX/pub/libvex_ir.h

index ef781e9eb94e57afec1783505d18a69b234058bd..55cf44778905e85751b320f655d4d7d545b9b48b 100644 (file)
@@ -43,10 +43,6 @@ IRBB* bbToIR_X86Instr ( UChar* x86code,
 enum {
     CC_OP_COPY, /* nothing to do -- ccs are in CC_SRC and up to date */
 
-    CC_OP_MULB, /* modify all flags, C, O = (CC_SRC != 0) */
-    CC_OP_MULW,
-    CC_OP_MULL,
-
     CC_OP_ADDB, /* modify all flags, CC_DST = res, CC_SRC = src1 */
     CC_OP_ADDW,
     CC_OP_ADDL,
@@ -83,7 +79,19 @@ enum {
     CC_OP_SARW, /* where res' is like res but shifted one bit less */
     CC_OP_SARL,
 
-    CC_OP_NB,
+    CC_OP_MULB, /* modify all flags, CC_DST = one arg */
+    CC_OP_MULW, /* CC_SRC = the other arg */
+    CC_OP_MULL,
+
+    CC_OP_MULLSB, /* modify all flags, CC_DST = one arg */
+    CC_OP_MULLSW, /* CC_SRC = the other arg */
+    CC_OP_MULLSL,
+
+    CC_OP_MULLUB, /* modify all flags, CC_DST = one arg */
+    CC_OP_MULLUW, /* CC_SRC = the other arg */
+    CC_OP_MULLUL,
+
+    CC_OP_NUMBER
 };
 
 /* called from generated code to evaluate the flags-thunk. */
index 272c2a919d1d9abbc646035685f8d6d01604457f..e1a86037731e874b6ed85756f160e93449758ef1 100644 (file)
@@ -472,6 +472,34 @@ static void setFlags_INC_DEC ( Bool inc, IRTemp dst, IRType ty )
 }
 
 
+/* For multiplies, just remember the two operands and a 
+   description of what kind of multiply. */
+
+static
+void setFlags_MUL ( IRType ty, IRTemp src1, IRTemp src2, UInt base_op )
+{
+   switch (ty) {
+   case Ity_I8:
+      stmt( IRStmt_Put( NULL, OFFB_CC_OP,  mkU32(base_op+0) ) );
+      stmt( IRStmt_Put( NULL, OFFB_CC_SRC, unop(Iop_8Uto32,mkexpr(src1)) ) );
+      stmt( IRStmt_Put( NULL, OFFB_CC_DST, unop(Iop_8Uto32,mkexpr(src2)) ) );
+      break;
+   case Ity_I16:
+      stmt( IRStmt_Put( NULL, OFFB_CC_OP,  mkU32(base_op+1) ) );
+      stmt( IRStmt_Put( NULL, OFFB_CC_SRC, unop(Iop_16Uto32,mkexpr(src1)) ) );
+      stmt( IRStmt_Put( NULL, OFFB_CC_DST, unop(Iop_16Uto32,mkexpr(src2)) ) );
+      break;
+   case Ity_I32:
+      stmt( IRStmt_Put( NULL, OFFB_CC_OP,  mkU32(base_op+2) ) );
+      stmt( IRStmt_Put( NULL, OFFB_CC_SRC, mkexpr(src1) ) );
+      stmt( IRStmt_Put( NULL, OFFB_CC_DST, mkexpr(src2) ) );
+      break;
+   default:
+      vpanic("setFlags_MUL(x86)");
+   }
+}
+
+
 /* Condition codes, using the Intel encoding.  */
 
 typedef
@@ -2081,15 +2109,18 @@ UInt dis_Grp2 ( UChar  sorb,
 //-- 
 //-- #  undef MODIFY_t2_AND_SET_CARRY_FLAG
 //-- }
-//-- 
-//-- 
-//-- 
-//-- /* Generate ucode to multiply the value in EAX/AX/AL by the register
-//--    specified by the ereg of modrm, and park the result in
-//--    EDX:EAX/DX:AX/AX. */
-//-- static void codegen_mul_A_D_Reg ( UCodeBlock* cb, Int sz, 
-//--                                   UChar modrm, Bool signed_multiply )
-//-- {
+
+
+
+/* Generate ucode to multiply the value in EAX/AX/AL by the register
+   specified by the ereg of modrm, and park the result in
+   EDX:EAX/DX:AX/AX. 
+
+   Viz, signed/unsigned widening multiply.
+*/
+static void codegen_mul_A_D_Reg ( Int sz, 
+                                  UChar modrm, Bool signed_multiply )
+{
 //--    Int helper = signed_multiply 
 //--                 ?
 //--                    (sz==1 ? VGOFF_(helper_imul_8_16) 
@@ -2099,10 +2130,35 @@ UInt dis_Grp2 ( UChar  sorb,
 //--                    (sz==1 ? VGOFF_(helper_mul_8_16)
 //--                           : (sz==2 ? VGOFF_(helper_mul_16_32) 
 //--                                    : VGOFF_(helper_mul_32_64)));
-//--    Int t1 = newTemp(cb);
-//--    Int ta = newTemp(cb);
+   IRType ty = szToITy(sz);
+   IRTemp t1 = newTemp(ty);
+   IRTemp t2 = newTemp(ty);
+   IRTemp tr = newTemp(ty);
+
 //--    uInstr0(cb, CALLM_S, 0);
 //--    uInstr2(cb, GET,   sz, ArchReg, eregOfRM(modrm), TempReg, t1);
+   assign( t1, getIReg(sz, eregOfRM(modrm)) );
+   assign( t2, getIReg(sz, R_EAX) );
+
+   switch (ty) {
+   case Ity_I32: {
+      IROp   hiOp   = signed_multiply ? Iop_MullS32_hi32 : Iop_MullU32_hi32;
+      IRTemp trHi32 = newTemp(Ity_I32);
+      setFlags_MUL ( Ity_I32, t1, t2, 
+                     signed_multiply ? CC_OP_MULLSB : CC_OP_MULLUB );
+      assign( tr,     binop(Iop_Mul32, mkexpr(t1), mkexpr(t2) ) );
+      assign( trHi32, binop(hiOp,  mkexpr(t1), mkexpr(t2) ) );
+      putIReg(4, R_EAX, mkexpr(tr));
+      putIReg(4, R_EDX, mkexpr(trHi32));
+      break;
+   }
+   default:
+      vpanic("codegen_mul_A_D_Reg(x86)");
+   }
+   DIP("%s%c %s\n", signed_multiply ? "imul" : "mul",
+                    nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
+}
+
 //--    uInstr1(cb, PUSH,  sz, TempReg, t1);
 //--    uInstr2(cb, GET,   sz, ArchReg, R_EAX,  TempReg, ta);
 //--    uInstr1(cb, PUSH,  sz, TempReg, ta);
@@ -2119,8 +2175,6 @@ UInt dis_Grp2 ( UChar  sorb,
 //--       uInstr2(cb, PUT,   2, TempReg, t1, ArchReg, R_EAX);
 //--    }
 //--    uInstr0(cb, CALLM_E, 0);
-//--    DIP("%s%c %s\n", signed_multiply ? "imul" : "mul",
-//--                     nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
 //-- 
 //-- }
 //-- 
@@ -2209,10 +2263,10 @@ UInt dis_Grp3 ( UChar sorb, Int sz, UInt delta )
            putIReg(sz, eregOfRM(modrm), mkexpr(dst1));
             DIP("neg%c %s\n", nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
             break;
-//--          case 4: /* MUL */
-//--             eip++;
-//--             codegen_mul_A_D_Reg ( cb, sz, modrm, False );
-//--             break;
+         case 4: /* MUL (unsigned widening) */
+            delta++;
+            codegen_mul_A_D_Reg ( sz, modrm, False );
+            break;
 //--          case 5: /* IMUL */
 //--             eip++;
 //--             codegen_mul_A_D_Reg ( cb, sz, modrm, True );
@@ -2655,51 +2709,84 @@ void dis_REP_op ( Condcode cond,
 /*--- Arithmetic, etc.                                     ---*/
 /*------------------------------------------------------------*/
 
-//-- /* (I)MUL E, G.  Supplied eip points to the modR/M byte. */
-//-- static
-//-- Addr dis_mul_E_G ( UCodeBlock* cb, 
-//--                    UChar       sorb,
-//--                    Int         size, 
-//--                    Addr        eip0,
-//--                    Bool        signed_multiply )
-//-- {
-//--    Int ta, tg, te;
-//--    UChar dis_buf[50];
-//--    UChar rm = getIByte(delta0);
-//--    ta = INVALID_TEMPREG;
-//--    te = newTemp(cb);
-//--    tg = newTemp(cb);
-//-- 
-//--    if (epartIsReg(rm)) {
-//--       vg_assert(signed_multiply);
-//--       uInstr2(cb, GET,  size, ArchReg, gregOfRM(rm), TempReg, tg);
-//--       uInstr2(cb, MUL,    size, ArchReg, eregOfRM(rm), TempReg, tg);
-//--       setFlagsFromUOpcode(cb, MUL);
-//--       uInstr2(cb, PUT,  size, TempReg, tg, ArchReg, gregOfRM(rm));
-//--       DIP("%smul%c %s, %s\n", signed_multiply ? "i" : "",
-//--                               nameISize(size), 
-//--                               nameIReg(size,eregOfRM(rm)),
-//--                               nameIReg(size,gregOfRM(rm)));
-//--       return 1+eip0;
-//--    } else {
-//--       UInt pair;
-//--       vg_assert(signed_multiply);
-//--       pair = disAMode ( cb, sorb, eip0, dis_buf );
-//--       ta = LOW24(pair);
-//--       uInstr2(cb, LOAD,  size, TempReg, ta, TempReg, te);
-//--       uInstr2(cb, GET,   size, ArchReg, gregOfRM(rm), TempReg, tg);
-//--       uInstr2(cb, MUL,    size, TempReg, te, TempReg, tg);
-//--       setFlagsFromUOpcode(cb, MUL);
-//--       uInstr2(cb, PUT,  size, TempReg, tg,    ArchReg, gregOfRM(rm));
-//-- 
-//--       DIP("%smul%c %s, %s\n", signed_multiply ? "i" : "",
-//--                               nameISize(size), 
-//--                               dis_buf, nameIReg(size,gregOfRM(rm)));
-//--       return HI8(pair)+eip0;
-//--    }
-//-- }
-//-- 
-//-- 
+#if 0
+static
+void do_mul_and_setFlags ( IRType ty, 
+                           IRTemp dst, IRTemp src1, IRTemp src2 )
+{
+   vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
+   setFlags_MUL( ty, src1, src2, CC_OP_MULB );
+   assign( dst, binop( mkSizedOp(ty,Iop_Mul8), 
+                       mkexpr(src1),
+                       mkexpr(src2)) );
+}
+
+static
+void do_mull_and_setFlags ( IRType ty, 
+                            Bool   sign,
+                            IRTemp dst, IRTemp src1, IRTemp src2 )
+{
+   vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32);
+   setFlags_MUL( ty, src1, src2, 
+                 sign ? CC_OP_MULLSB : CC_OP_MULLUB );
+   assign( dst, 
+           binop( mkSizedOp(ty, sign ? Iop_MullS8 : Iop_MullU8), 
+                  mkexpr(src1), 
+                  mkexpr(src2)) );
+}
+#endif
+
+/* (I)MUL E, G.  Supplied eip points to the modR/M byte. */
+static
+UInt dis_mul_E_G ( UChar       sorb,
+                   Int         size, 
+                   UInt        delta0,
+                   Bool        signed_multiply )
+{
+   
+  //   UChar dis_buf[50];
+   UChar  rm = getIByte(delta0);
+   IRType ty = szToITy(size);
+   //IRTemp ta = INVALID_IRTEMP;
+   IRTemp te = newTemp(size);
+   IRTemp tg = newTemp(size);
+
+   if (epartIsReg(rm)) {
+      vassert(signed_multiply);
+      assign( tg, getIReg(size, gregOfRM(rm)) );
+      assign( te, getIReg(size, eregOfRM(rm)) );
+      setFlags_MUL ( ty, te, tg, CC_OP_MULB );
+      putIReg(size, gregOfRM(rm), 
+             binop(mkSizedOp(ty,Iop_Mul8),
+                   mkexpr(te), mkexpr(tg)));
+
+      DIP("%smul%c %s, %s\n", signed_multiply ? "i" : "",
+                              nameISize(size), 
+                              nameIReg(size,eregOfRM(rm)),
+                              nameIReg(size,gregOfRM(rm)));
+      return 1+delta0;
+   } else {
+     vassert(0+0==0);
+#if 0
+      UInt pair;
+      vg_assert(signed_multiply);
+      pair = disAMode ( cb, sorb, eip0, dis_buf );
+      ta = LOW24(pair);
+      uInstr2(cb, LOAD,  size, TempReg, ta, TempReg, te);
+      uInstr2(cb, GET,   size, ArchReg, gregOfRM(rm), TempReg, tg);
+      uInstr2(cb, MUL, size, TempReg, te, TempReg, tg);
+      setFlagsFromUOpcode(cb, MUL);
+      uInstr2(cb, PUT,  size, TempReg, tg,    ArchReg, gregOfRM(rm));
+
+      DIP("%smul%c %s, %s\n", signed_multiply ? "i" : "",
+                              nameISize(size), 
+                              dis_buf, nameIReg(size,gregOfRM(rm)));
+      return HI8(pair)+eip0;
+#endif
+   }
+}
+
+
 //-- /* IMUL I * E -> G.  Supplied eip points to the modR/M byte. */
 //-- static
 //-- Addr dis_imul_I_E_G ( UCodeBlock* cb, 
@@ -7107,12 +7194,12 @@ static UInt disInstr ( UInt delta, Bool* isEnd )
 //--          uInstr2(cb, STORE, 4, TempReg, t1, TempReg, t2);
 //--          DIP("movnti %s,%s\n", nameIReg(4,gregOfRM(modrm)), dis_buf);
 //--          break;
-//-- 
-//--       /* =-=-=-=-=-=-=-=-=- MUL/IMUL =-=-=-=-=-=-=-=-=-= */
-//-- 
-//--       case 0xAF: /* IMUL Ev, Gv */
-//--          eip = dis_mul_E_G ( cb, sorb, sz, eip, True );
-//--          break;
+
+      /* =-=-=-=-=-=-=-=-=- MUL/IMUL =-=-=-=-=-=-=-=-=-= */
+
+      case 0xAF: /* IMUL Ev, Gv */
+         delta = dis_mul_E_G ( sorb, sz, delta, True );
+         break;
 
       /* =-=-=-=-=-=-=-=-=- Jcond d32 -=-=-=-=-=-=-=-=-= */
       case 0x80:
index 4a7af191e7c75444e192c5ec558fd8eda3f4c321..6defc2e93e5c86afc5415016fc0a4ec6f1d78686 100644 (file)
@@ -87,6 +87,12 @@ void ppIROp ( IROp op )
       case Iop_16Sto32: vex_printf("16Sto32"); return;
       case Iop_32to1:   vex_printf("32to1");   return;
       case Iop_1Uto8:   vex_printf("1Uto8");   return;
+      case Iop_MullS8:  vex_printf("MullS8");  return;
+      case Iop_MullS16: vex_printf("MullS16"); return;
+      case Iop_MullS32_hi32: vex_printf("MullS32_hi32"); return;
+      case Iop_MullU8:       vex_printf("MullU8");       return;
+      case Iop_MullU16:      vex_printf("MullU16");      return;
+      case Iop_MullU32_hi32: vex_printf("MullU32_hi32"); return;
       default:        vpanic("ppIROp(1)");
    }
   
index 6393e7c8aec6093d143087131498a121aab55a44..72e2238cc6764d9e7af2df7ba42c048a41074d49 100644 (file)
@@ -89,7 +89,10 @@ typedef
       /* Conversions */
       Iop_8Uto16, Iop_8Uto32, Iop_16Uto32,
       Iop_8Sto16, Iop_8Sto32, Iop_16Sto32,
-      /* Specials */
+      /* Widening multiplies */
+      Iop_MullS8, Iop_MullS16, Iop_MullS32_hi32,
+      Iop_MullU8, Iop_MullU16, Iop_MullU32_hi32,
+      /* 1-bit stuff */
       Iop_32to1, /* :: Ity_I32 -> Ity_Bit, just select bit[0] */
       Iop_1Uto8  /* :: Ity_Bit -> Ity_I8, unsigned widen */
    }