]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
This creates a new UInstr for multiply. This is mainly so that memcheck
authorJeremy Fitzhardinge <jeremy@valgrind.org>
Tue, 14 Oct 2003 21:49:11 +0000 (21:49 +0000)
committerJeremy Fitzhardinge <jeremy@valgrind.org>
Tue, 14 Oct 2003 21:49:11 +0000 (21:49 +0000)
can treat it like add and generate partially-defined results of multiply
with partially defined arguments.  It may also speed things up a bit,
if they use lots of multiplies.

This change only deals with signed "new style" multiplies.  That the x86
has two quite different kinds of multiply instructions: the "old-style"
signed and unsigned multiply which uses fixed registers (eax:edx) and
generates a result twice the size of the arguments, and the newer signed
multiple which takes general addressing modes.  It seems that gcc always
(almost always?) generates the new signed multiply instructions, except
for byte-sized multiplies.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1925

coregrind/vg_from_ucode.c
coregrind/vg_to_ucode.c
coregrind/vg_translate.c
include/vg_skin.h
memcheck/mc_translate.c

index 3e8c462d55e78f724f8073cd5cfcc4473b518570..94fd72810b9bfe94a196df892228ccdba4028d83 100644 (file)
@@ -2879,6 +2879,91 @@ static void synth_nonshiftop_lit_offregmem ( Bool simd_flags,
 }
 
 
+static void synth_mul_reg_reg ( Bool upd_cc, 
+                               Opcode opcode, Int size, 
+                               Int reg1, Int reg2 )
+{
+   VG_(new_emit)(upd_cc, FlagsEmpty, FlagsOSZACP);
+
+   switch (size) {
+   case 2:
+      VG_(emitB)(0x66);
+      /* FALLTHROUGH */
+   case 4:
+      VG_(emitB)(0x0F);
+      VG_(emitB)(0xAF);
+      VG_(emit_amode_ereg_greg)(reg1, reg2);
+      break;
+
+   case 1:
+      VG_(core_panic)("can't do byte mul");
+      break;
+   }
+   if (dis)
+      VG_(printf)("\n\t\timul%c\t%s, %s\n",
+                 nameISize(size),
+                 nameIReg(size, reg1),
+                 nameIReg(size, reg2));
+}
+
+static void synth_mul_lit_reg ( Bool upd_cc,
+                               Opcode opcode, Int size, 
+                               UInt lit, Int reg )
+{
+   VG_(new_emit)(upd_cc, FlagsEmpty, FlagsOSZACP);
+
+   switch (size) {
+   case 2:
+      VG_(emitB)(0x66);
+      /* FALLTHROUGH */
+   case 4:
+      VG_(emitB)(0x69);
+      VG_(emit_amode_ereg_greg)(reg, 0);
+      if (size == 2)
+        VG_(emitW)(lit);
+      else
+        VG_(emitL)(lit);
+      break;
+
+   case 1:
+      VG_(core_panic)("can't do byte mul");
+      break;
+   }
+   if (dis)
+      VG_(printf)("\n\t\timul%c\t%d, %s\n",
+                 nameISize(size),
+                 lit,
+                 nameIReg(size, reg));
+}
+
+static void synth_mul_offregmem_reg ( 
+   Bool upd_cc,
+   Opcode opcode, Int size, 
+   Int off, Int areg, Int reg )
+{
+   VG_(new_emit)(upd_cc, FlagsEmpty, FlagsOSZACP);
+
+   switch(size) {
+   case 2:
+      VG_(emitB)(0x66);
+      /* FALLTHROUGH */
+   case 4:
+      VG_(emitB)(0x0F);
+      VG_(emitB)(0xAF);
+      VG_(emit_amode_offregmem_reg)(off, areg, reg);
+      break;
+
+   case 1:
+      VG_(core_panic)("can't do byte mul");
+   }
+
+   if (dis)
+      VG_(printf)("\n\t\timul%c\t0x%x(%s), %s\n",
+                 nameISize(size), off, nameIReg(4,areg),nameIReg(size,reg));
+
+}
+
+
 static void synth_push_reg ( Int size, Int reg )
 {
    switch (size) {
@@ -3528,6 +3613,30 @@ static void emitUInstr ( UCodeBlock* cb, Int i,
          break;
       }
 
+      case MUL: {
+        vg_assert(u->tag2 == RealReg);
+
+        switch(u->tag1) {
+           case Literal:
+              synth_mul_lit_reg(anyFlagUse(u),
+                                u->opcode, u->size, u->lit32, u->val2);
+              break;
+           case RealReg:
+              synth_mul_reg_reg(anyFlagUse(u),
+                                u->opcode, u->size, u->val1, u->val2);
+              break;
+           case ArchReg:
+              synth_mul_offregmem_reg(anyFlagUse(u),
+                                      u->opcode, u->size,
+                                      spillOrArchOffset(u->size, u->tag1, u->val1), 
+                                      R_EBP, u->val2);
+              break;
+           
+           default: VG_(core_panic)("emitUInstr:MUL");
+        }
+        break;
+      }
+
       case SBB:
       case ADC:
       case XOR:
index 3992e1d82c145fc192de51b4905356a30622b039..ef147558292e23356b81e8ea8ba987b8dee187ca 100644 (file)
@@ -271,6 +271,8 @@ static void setFlagsFromUOpcode ( UCodeBlock* cb, Int uopc )
          uFlagsRWU(cb, FlagsEmpty, FlagsOSZCP,  FlagA); break;
       case ADC: case SBB: 
          uFlagsRWU(cb, FlagC,      FlagsOSZACP, FlagsEmpty); break;
+      case MUL: case UMUL:
+        uFlagsRWU(cb, FlagsEmpty, FlagsOC,     FlagsSZAP); break;
       case ADD: case SUB: case NEG: 
          uFlagsRWU(cb, FlagsEmpty, FlagsOSZACP, FlagsEmpty); break;
       case INC: case DEC:
@@ -1446,7 +1448,7 @@ static void codegen_mul_A_D_Reg ( UCodeBlock* cb, Int sz,
       uInstr1(cb, POP,   2, TempReg, t1);
       uInstr2(cb, PUT,   2, TempReg, t1, ArchReg, R_EAX);
    }
-       uInstr0(cb, CALLM_E, 0);
+   uInstr0(cb, CALLM_E, 0);
    if (dis) VG_(printf)("%s%c %s\n", signed_multiply ? "imul" : "mul",
                         nameISize(sz), nameIReg(sz, eregOfRM(modrm)));
 
@@ -2200,38 +2202,19 @@ Addr dis_mul_E_G ( UCodeBlock* cb,
                    Addr        eip0,
                    Bool        signed_multiply )
 {
-   Int ta, tg, te, helper;
+   Int ta, tg, te;
    UChar dis_buf[50];
    UChar rm = getUChar(eip0);
    ta = INVALID_TEMPREG;
    te = newTemp(cb);
    tg = newTemp(cb);
 
-   switch (size) {
-      case 4: helper = signed_multiply ? VGOFF_(helper_imul_32_64) 
-                                       : VGOFF_(helper_mul_32_64);
-              break;
-      case 2: helper = signed_multiply ? VGOFF_(helper_imul_16_32) 
-                                       : VGOFF_(helper_mul_16_32);
-              break;
-      case 1: helper = signed_multiply ? VGOFF_(helper_imul_8_16)
-                                       : VGOFF_(helper_mul_8_16);
-              break;
-      default: VG_(core_panic)("dis_mul_E_G");
-   }
-
-   uInstr0(cb, CALLM_S, 0);
    if (epartIsReg(rm)) {
-      uInstr2(cb, GET,   size, ArchReg, eregOfRM(rm), TempReg, te);
-      uInstr2(cb, GET,   size, ArchReg, gregOfRM(rm), TempReg, tg);
-      uInstr1(cb, PUSH,  size, TempReg, te);
-      uInstr1(cb, PUSH,  size, TempReg, tg);
-      uInstr1(cb, CALLM, 0,    Lit16,   helper);
-      uFlagsRWU(cb, FlagsEmpty, FlagsOC, FlagsSZAP);
-      uInstr1(cb, CLEAR, 0,    Lit16,   4);
-      uInstr1(cb, POP,   size, TempReg, tg);
-      uInstr2(cb, PUT,   size, TempReg, tg,   ArchReg, gregOfRM(rm));
-      uInstr0(cb, CALLM_E, 0);
+      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));
       if (dis) VG_(printf)("%smul%c %s, %s\n",
                            signed_multiply ? "i" : "",
                            nameISize(size), 
@@ -2239,18 +2222,16 @@ Addr dis_mul_E_G ( UCodeBlock* cb,
                            nameIReg(size,gregOfRM(rm)));
       return 1+eip0;
    } else {
-      UInt pair = disAMode ( cb, sorb, eip0, dis?dis_buf:NULL);
+      UInt pair;
+      vg_assert(signed_multiply);
+      pair = disAMode ( cb, sorb, eip0, dis?dis_buf:NULL);
       ta = LOW24(pair);
       uInstr2(cb, LOAD,  size, TempReg, ta, TempReg, te);
       uInstr2(cb, GET,   size, ArchReg, gregOfRM(rm), TempReg, tg);
-      uInstr1(cb, PUSH,  size, TempReg, te);
-      uInstr1(cb, PUSH,  size, TempReg, tg);
-      uInstr1(cb, CALLM, 0,    Lit16, helper);
-      uFlagsRWU(cb, FlagsEmpty, FlagsOC, FlagsSZAP);
-      uInstr1(cb, CLEAR, 0,    Lit16,   4);
-      uInstr1(cb, POP,   size, TempReg, tg);
-      uInstr2(cb, PUT,   size, TempReg, tg,   ArchReg, gregOfRM(rm));
-      uInstr0(cb, CALLM_E, 0);
+      uInstr2(cb, MUL, size, TempReg, te, TempReg, tg);
+      setFlagsFromUOpcode(cb, MUL);
+      uInstr2(cb, PUT,  size, TempReg, tg,    ArchReg, gregOfRM(rm));
+
       if (dis) VG_(printf)("%smul%c %s, %s\n",
                            signed_multiply ? "i" : "",
                            nameISize(size), 
@@ -2268,30 +2249,20 @@ Addr dis_imul_I_E_G ( UCodeBlock* cb,
                       Addr        eip,
                       Int         litsize )
 {
-   Int ta, te, tl, helper, d32;
+   Int ta, te, tl, d32;
    UChar dis_buf[50];
    UChar rm = getUChar(eip);
    ta = INVALID_TEMPREG;
    te = newTemp(cb);
    tl = newTemp(cb);
 
-   switch (size) {
-      case 4: helper = VGOFF_(helper_imul_32_64); break;
-      case 2: helper = VGOFF_(helper_imul_16_32); break;
-      case 1: helper = VGOFF_(helper_imul_8_16); break;
-      default: VG_(core_panic)("dis_imul_I_E_G");
-   }
-
-   uInstr0(cb, CALLM_S, 0);
    if (epartIsReg(rm)) {
       uInstr2(cb, GET,   size, ArchReg, eregOfRM(rm), TempReg, te);
-      uInstr1(cb, PUSH,  size, TempReg, te);
       eip++;
    } else {
       UInt pair = disAMode ( cb, sorb, eip, dis?dis_buf:NULL);
       ta = LOW24(pair);
       uInstr2(cb, LOAD,  size, TempReg, ta, TempReg, te);
-      uInstr1(cb, PUSH,  size, TempReg, te);
       eip += HI8(pair);
    }
 
@@ -2300,13 +2271,9 @@ Addr dis_imul_I_E_G ( UCodeBlock* cb,
 
    uInstr2(cb, MOV,   size, Literal, 0,   TempReg, tl);
    uLiteral(cb, d32);
-   uInstr1(cb, PUSH,  size, TempReg, tl);
-   uInstr1(cb, CALLM, 0,    Lit16, helper);
-   uFlagsRWU(cb, FlagsEmpty, FlagsOC, FlagsSZAP);
-   uInstr1(cb, CLEAR, 0,    Lit16,   4);
-   uInstr1(cb, POP,   size, TempReg, te);
+   uInstr2(cb, MUL,   size, TempReg, tl,   TempReg, te);
+   setFlagsFromUOpcode(cb, MUL);
    uInstr2(cb, PUT,   size, TempReg, te,   ArchReg, gregOfRM(rm));
-   uInstr0(cb, CALLM_E, 0);
 
    if (dis) {
       if (epartIsReg(rm)) {
index bb638168528f22642c0fe2ed66522e3af246a4e9..7863c5968e9cf70259f21a3fe12d2ffd4fc2fc55 100644 (file)
@@ -461,6 +461,8 @@ Bool VG_(saneUInstr) ( Bool beforeRA, Bool beforeLiveness, UInstr* u )
 #  define Ls3 (u->tag3 == Lit16)
 #  define TRL1 (TR1 || L1)
 #  define TRAL1 (TR1 || A1 || L1)
+#  define TRA1 (TR1 || A1)
+#  define TRA2 (TR2 || A2)
 #  define N1  (u->tag1 == NoValue)
 #  define N2  (u->tag2 == NoValue)
 #  define N3  (u->tag3 == NoValue)
@@ -519,6 +521,7 @@ Bool VG_(saneUInstr) ( Bool beforeRA, Bool beforeLiveness, UInstr* u )
    case CLEAR:  return LIT0 && SZ0  && CC0 &&  Ls1 &&  N2 &&  N3 && XOTHER;
    case AND:
    case OR:     return LIT0 && SZi  && CCa &&  TR1 && TR2 &&  N3 && XOTHER;
+   case MUL:    return LIT0 && SZ42 && CCa && TRA1 &&TRA2 &&  N3 && XOTHER;
    case ADD:
    case XOR:
    case SUB:    return LITm && SZi  && CCa &&TRAL1 && TR2 &&  N3 && XOTHER;
@@ -840,6 +843,7 @@ Char* VG_(name_UOpcode) ( Bool upper, Opcode opc )
       case ROR:   return (upper ? "ROR" : "ror");
       case RCL:   return (upper ? "RCL" : "rcl");
       case RCR:   return (upper ? "RCR" : "rcr");
+      case MUL:   return (upper ? "MUL" : "mul");
       case NOT:   return (upper ? "NOT" : "not");
       case NEG:   return (upper ? "NEG" : "neg");
       case INC:   return (upper ? "INC" : "inc");
@@ -1172,7 +1176,8 @@ void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness )
       case ADD: case ADC: case AND: case OR:  
       case XOR: case SUB: case SBB:   
       case SHL: case SHR: case SAR: 
-      case ROL: case ROR: case RCL: case RCR:   
+      case ROL: case ROR: case RCL: case RCR:
+      case MUL:   
          VG_(pp_UOperand)(u, 1, u->size, False); 
          VG_(printf)(", ");
          VG_(pp_UOperand)(u, 2, u->size, False);
@@ -1308,6 +1313,7 @@ Int VG_(get_reg_usage) ( UInstr* u, Tag tag, Int* regs, Bool* isWrites )
       case CMOV:
       case ADD: case ADC: case AND: case OR:  
       case XOR: case SUB: case SBB:   
+      case MUL:
          RD(1); RD(2); WR(2); break;
 
       case SHL: case SHR: case SAR: 
@@ -1398,6 +1404,7 @@ Int maybe_uinstrReadsArchReg ( UInstr* u )
       case XOR: case SUB: case SBB:   
       case SHL: case SHR: case SAR: case ROL: 
       case ROR: case RCL: case RCR:
+      case MUL:
          if (u->tag1 == ArchReg) 
             return containingArchRegOf ( u->size, u->val1 ); 
          else
@@ -1614,6 +1621,7 @@ static void vg_improve ( UCodeBlock* cb )
                case ADC: case SBB:
                case SHL: case SHR: case SAR: case ROL: case ROR:
                case RCL: case RCR:
+              case MUL:
                   if (dis) 
                      VG_(printf)(
                         "   at %2d: change ArchReg %S to TempReg t%d\n", 
index 697126d1e56fb77b4afa5c66e20bedfa85beb754..d8d168a3733cf4b5858c48f46b4e9c82121c1db0 100644 (file)
@@ -551,6 +551,7 @@ typedef
       CMOV,        /* Used for cmpxchg and cmov       */
 
       /* Arithmetic/logical ops */
+      MUL, UMUL,                         /* Multiply */
       ADD, ADC, SUB, SBB,                 /* Add/subtract (w/wo carry)     */
       AND, OR,  XOR, NOT,                 /* Boolean ops                   */
       SHL, SHR, SAR, ROL, ROR, RCL, RCR,  /* Shift/rotate (w/wo carry)     */
index ed1acbc57eda2a38ba2a7512b197500ec5324de7..108a606ab18257ce5c659de923b7786ff545a8f8 100644 (file)
@@ -860,6 +860,7 @@ static UCodeBlock* memcheck_instrument ( UCodeBlock* cb_in )
          */
          case ADD: case SUB:
          case ADC: case SBB:
+         case MUL:
             qd = SHADOW(u_in->val2);
             qs = getOperandShadow(cb, u_in->size, u_in->tag1, u_in->val1);
             create_UifU(cb, u_in->size, qs, qd);