]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Fill in a few more SSE/SSE2 insns, with current aim of being able to
authorJulian Seward <jseward@acm.org>
Thu, 12 Jun 2003 00:56:06 +0000 (00:56 +0000)
committerJulian Seward <jseward@acm.org>
Thu, 12 Jun 2003 00:56:06 +0000 (00:56 +0000)
run Qt-3.1 as built with "icc -xW" (P4 code generation).  Hopefully by
now I've worked through most SSE/SSE2 conceptual nasties, and it's
mostly a question of filling in the gaps.

I think I might have created a bug of some kind with SSE3g_RegWr.  My
current test app segfaults if I run without --optimise=no, which makes
me think I've written something erroneous in the UInstr predicates
controlling optimisation.  I don't know what though.

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

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

index c609a89f7cb233e1543e8d76436e748a91a81680..0b90f11146aa527be28eafdd441bcf5cdf5aec60 100644 (file)
@@ -1464,7 +1464,8 @@ static void emit_SSE3g ( FlagSet uses_sflags,
                          UChar second_byte, 
                         UChar third_byte,
                         UChar fourth_byte,
-                         Int ireg )
+                         Int ireg,
+                         Bool reads_ireg )
 {
    VG_(new_emit)(True, uses_sflags, sets_sflags);
    VG_(emitB) ( first_byte );
@@ -1475,10 +1476,14 @@ static void emit_SSE3g ( FlagSet uses_sflags,
    fourth_byte |= (ireg & 7); /* patch in our ireg */
    VG_(emitB) ( fourth_byte );
    if (dis)
-      VG_(printf)("\n\t\tsse-reg-to-xmmreg--0x%x:0x%x:0x%x:0x%x-(%s)\n", 
-                  (UInt)first_byte, (UInt)second_byte, 
-                  (UInt)third_byte, (UInt)fourth_byte,
-                  nameIReg(4,ireg) );
+      VG_(printf)(
+         reads_ireg
+            ? "\n\t\tireg-to-ssereg--0x%x:0x%x:0x%x:0x%x-(%s)\n" 
+            : "\n\t\tssereg-to-ireg--0x%x:0x%x:0x%x:0x%x-(%s)\n", 
+         (UInt)first_byte, (UInt)second_byte, 
+         (UInt)third_byte, (UInt)fourth_byte,
+         nameIReg(4,ireg) 
+      );
 }
 
 static void emit_SSE4 ( FlagSet uses_sflags, 
@@ -3713,7 +3718,6 @@ static void emitUInstr ( UCodeBlock* cb, Int i,
          vg_assert(u->tag1 == Lit16);
          vg_assert(u->tag2 == Lit16);
          vg_assert(u->tag3 == RealReg);
-         vg_assert(!anyFlagUse(u));
          if (!(*sselive)) {
             emit_get_sse_state();
             *sselive = True;
@@ -3727,6 +3731,7 @@ static void emitUInstr ( UCodeBlock* cb, Int i,
          break;
 
       case SSE3g_RegRd:
+      case SSE3g_RegWr:
          vg_assert(u->size == 4);
          vg_assert(u->tag1 == Lit16);
          vg_assert(u->tag2 == Lit16);
@@ -3741,7 +3746,8 @@ static void emitUInstr ( UCodeBlock* cb, Int i,
                       u->val1 & 0xFF,
                       (u->val2 >> 8) & 0xFF,
                       u->val2 & 0xFF,
-                      u->val3 );
+                      u->val3,
+                      u->opcode==SSE3g_RegRd ? True : False );
          break;
 
       case SSE4:
index 98374ecc23de767b4ff55bccfcb4f3e304d0127b..31dc89be8b4fa92d570a1d05c4ecac6b1202c9c1 100644 (file)
@@ -3293,6 +3293,7 @@ Addr dis_SSE3_reg_or_mem ( UCodeBlock* cb,
                            UChar opc2, 
                            UChar opc3 )
 {
+   UChar dis_buf[50];
    UChar modrm = getUChar(eip);
    if (epartIsReg(modrm)) {
       /* Completely internal SSE insn. */
@@ -3305,7 +3306,18 @@ Addr dis_SSE3_reg_or_mem ( UCodeBlock* cb,
                      nameXMMReg(gregOfRM(modrm)) );
       eip++;
    } else {
-      VG_(core_panic)("dis_SSE3_reg_or_mem: mem");
+      UInt pair = disAMode ( cb, sorb, eip, dis?dis_buf:NULL );
+      Int  tmpa = LOW24(pair);
+      eip += HI8(pair);
+      uInstr3(cb, SSE3a_MemRd, sz,
+                  Lit16, (((UShort)(opc1)) << 8) | ((UShort)opc2),
+                  Lit16, (((UShort)(opc3)) << 8) | ((UShort)modrm),
+                  TempReg, tmpa);
+      if (dis)
+         VG_(printf)("%s %s, %s\n", 
+                     name,
+                     dis_buf,
+                     nameXMMReg(gregOfRM(modrm)));
    }
    return eip;
 }
@@ -3608,8 +3620,53 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
       goto decode_success;
    }
 
-   /* CVTSI2SS -- convert int reg to low 4 bytes of XMM reg. */
-   if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x2A) {
+   /* CVTTSD2SI -- convert a double-precision float value in memory or
+      xmm reg to int and put it in an ireg. */
+   if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x2C) {
+      vg_assert(sz == 4);
+      modrm = insn[3];
+      if (epartIsReg(modrm)) {
+         /* We're moving a value in an xmm reg to an ireg. */
+         eip += 4;
+        t1 = newTemp(cb);
+         uInstr3(cb, SSE3g_RegWr, 4,
+                     Lit16, (((UShort)insn[0]) << 8) | (UShort)insn[1],
+                     Lit16, (((UShort)insn[2]) << 8) | (UShort)modrm,
+                     TempReg, t1 );
+         uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, gregOfRM(modrm));
+        if (dis)
+            VG_(printf)("cvttsd2si %s, %s\n", 
+                        nameXMMReg(eregOfRM(modrm)),
+                        nameIReg(4,gregOfRM(modrm)) );
+      } else {
+#if 0
+         /* So, we're reading memory and writing an ireg.  This calls
+            for the ultra-horrible SSE3ag_MemRd_RegWr uinstr. */
+         t1 = newTemp(cb); /* t1 holds value on its way to ireg */
+         pair = disAMode ( cb, sorb, eip+3, dis?dis_buf:NULL );
+         t2   = LOW24(pair); /* t2 holds addr */
+         eip += 3+HI8(pair);
+         uInstr2(cb, SSE3ag_MemRd_RegWr, 8,
+                     TempReg, t2, /* address */
+                     TempReg, t1 /* dest */);
+         uLiteral(cb, (((UInt)insn[0]) << 16)
+                      | (((UInt)insn[1]) << 8)
+                      | ((UInt)insn[2]) );
+         uInstr2(cb, PUT, 4, TempReg, t1, ArchReg, gregOfRM(modrm));
+        /* PRINTING CODE */
+#endif
+         VG_(core_panic)("CVTTSD2SI mem");
+      }
+      goto decode_success;
+   }
+
+   /* CVTSI2SS -- convert int reg, or int value in memory, to low 4
+      bytes of XMM reg. */
+   /* CVTSI2SD -- convert int reg, or int value in memory, to low 8
+      bytes of XMM reg. */
+   if ((insn[0] == 0xF3 /*CVTSI2SS*/ || insn[0] == 0xF2 /* CVTSI2SD*/)
+       && insn[1] == 0x0F && insn[2] == 0x2A) {
+      Char* s_or_d = insn[0]==0xF3 ? "s" : "d";
       vg_assert(sz == 4);
       modrm = insn[3];
       t1 = newTemp(cb);
@@ -3621,8 +3678,9 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
                      TempReg, t1 );
          eip += 4;
         if (dis)
-            VG_(printf)("cvtsi2ss %s, %s\n", nameIReg(4,eregOfRM(modrm)), 
-                                             nameXMMReg(gregOfRM(modrm)));
+            VG_(printf)("cvtsi2s%s %s, %s\n", s_or_d,
+                                              nameIReg(4,eregOfRM(modrm)), 
+                                              nameXMMReg(gregOfRM(modrm)));
       } else {
          pair = disAMode ( cb, sorb, eip+3, dis?dis_buf:NULL );
          t2   = LOW24(pair);
@@ -3633,8 +3691,9 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
                      Lit16, (((UShort)insn[2]) << 8) | (UShort)insn[3],
                      TempReg, t1 );
         if (dis)
-            VG_(printf)("cvtsi2ss %s, %s\n", dis_buf,
-                                             nameXMMReg(gregOfRM(modrm)));
+            VG_(printf)("cvtsi2s%s %s, %s\n", s_or_d,
+                                              dis_buf,
+                                              nameXMMReg(gregOfRM(modrm)));
       }
       goto decode_success;
    }
@@ -3655,6 +3714,14 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
       goto decode_success;
    }
 
+   /* CVTSD2SS -- convert one single double. to float. */
+   if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5A) {
+      vg_assert(sz == 4);
+      eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, 8, "cvtsd2ss",
+                                      insn[0], insn[1], insn[2] );
+      goto decode_success;
+   }
+
    /* SHUFPS */
    if (insn[0] == 0x0F && insn[1] == 0xC6) {
       vg_assert(sz == 4);
@@ -3679,6 +3746,22 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
       goto decode_success;
    }
 
+   /* DIVSD */
+   if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5E) {
+      vg_assert(sz == 4);
+      eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, 8, "divsd",
+                                      insn[0], insn[1], insn[2] );
+      goto decode_success;
+   }
+
+   /* ADDSD */
+   if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x58) {
+      vg_assert(sz == 4);
+      eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+3, 8, "addsd",
+                                      insn[0], insn[1], insn[2] );
+      goto decode_success;
+   }
+
    /* ADDPS */
    if (insn[0] == 0x0F && insn[1] == 0x58) {
       vg_assert(sz == 4);
@@ -3713,6 +3796,17 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
       goto decode_success;
    }
 
+   /* COMISD (src)xmmreg-or-mem, (dst)xmmreg */
+   if (sz == 2
+       && insn[0] == 0x0F && insn[1] == 0x2F) {
+      eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 8, "comisd",
+                                      0x66, insn[0], insn[1] );
+      vg_assert(LAST_UINSTR(cb).opcode == SSE3a_MemRd 
+                || LAST_UINSTR(cb).opcode == SSE4);
+      uFlagsRWU(cb, FlagsEmpty, FlagsZCP, FlagsEmpty);
+      goto decode_success;
+   }
+
    /* MOVSD -- move 8 bytes of XMM reg to/from XMM reg or mem. */
    if (insn[0] == 0xF2
        && insn[1] == 0x0F 
index e2d998ebd9067fb23b6b161a7d5982041de9ee25..b2e30ced24bc5e64961a65403d7fafdac7c95350 100644 (file)
@@ -561,8 +561,9 @@ Bool VG_(saneUInstr) ( Bool beforeRA, Bool beforeLiveness, UInstr* u )
    case SSE2a_MemWr:  return LIT0 && SZ416 && CC0  && Ls1 && Ls2 && TR3 && XOTHER;
    case SSE2a_MemRd:  return LIT0 && SZ416 && CC0  && Ls1 && Ls2 && TR3 && XOTHER;
    case SSE3a_MemWr:  return LIT0 && SZsse && CC0  && Ls1 && Ls2 && TR3 && XOTHER;
-   case SSE3a_MemRd:  return LIT0 && SZsse && CC0  && Ls1 && Ls2 && TR3 && XOTHER;
+   case SSE3a_MemRd:  return LIT0 && SZsse && CCf  && Ls1 && Ls2 && TR3 && XOTHER;
    case SSE3g_RegRd:  return LIT0 && SZ4   && CC0  && Ls1 && Ls2 && TR3 && XOTHER;
+   case SSE3g_RegWr:  return LIT0 && SZ4   && CC0  && Ls1 && Ls2 && TR3 && XOTHER;
    case SSE3:         return LIT0 && SZ0   && CC0  && Ls1 && Ls2 && N3  && XOTHER;
    case SSE4:         return LIT0 && SZ0   && CC0  && Ls1 && Ls2 && N3  && XOTHER;
    default: 
@@ -879,6 +880,7 @@ Char* VG_(name_UOpcode) ( Bool upper, Opcode opc )
       case SSE2a_MemWr: return "SSE2a_MWr";
       case SSE2a_MemRd: return "SSE2a_MRd";
       case SSE3g_RegRd: return "SSE3g_RRd";
+      case SSE3g_RegWr: return "SSE3g_RWr";
       case SSE3:        return "SSE3";
       case SSE4:        return "SSE4";
       case SSE3a_MemWr: return "SSE3a_MWr";
@@ -1049,6 +1051,7 @@ void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness )
          break;
 
       case SSE3g_RegRd:
+      case SSE3g_RegWr:
          VG_(printf)("0x%x:0x%x:0x%x:0x%x",
                      (u->val1 >> 8) & 0xFF, u->val1 & 0xFF, 
                      (u->val2 >> 8) & 0xFF, u->val2 & 0xFF );
@@ -1216,7 +1219,9 @@ Int VG_(get_reg_usage) ( UInstr* u, Tag tag, Int* regs, Bool* isWrites )
       case SSE3a_MemWr:
       case SSE3a_MemRd:
       case SSE2a_MemWr: 
-      case SSE2a_MemRd: RD(3);
+      case SSE2a_MemRd: RD(3); break;
+
+      case SSE3g_RegWr: WR(3); break;
 
       case MMX2_RegRd: RD(2); break;
       case MMX2_RegWr: WR(2); break;
@@ -1375,7 +1380,7 @@ Int maybe_uinstrReadsArchReg ( UInstr* u )
       case MMX2_RegRd: case MMX2_RegWr:
       case SSE2a_MemWr: case SSE2a_MemRd:
       case SSE3a_MemWr: case SSE3a_MemRd:
-      case SSE3g_RegRd:
+      case SSE3g_RegRd: case SSE3g_RegWr:
       case SSE4: case SSE3:
       case WIDEN:
       /* GETSEG and USESEG are to do with ArchRegS, not ArchReg */
@@ -2244,7 +2249,7 @@ void VG_(translate) ( /*IN*/  ThreadState* tst,
    UChar*      final_code;
    UCodeBlock* cb;
    Bool        notrace_until_done;
-   Int         notrace_until_limit = 0;
+   Int         notrace_until_limit = 15000;
 
    VGP_PUSHCC(VgpTranslate);
    debugging_translation
index 5ef6581c6f26e9f731a68e4983354a72ff2095e0..fc4c1909faeb917544fe702c6f23d550845bf23d 100644 (file)
@@ -643,6 +643,22 @@ typedef
       */
       SSE3g_RegRd,
 
+      /* 4 bytes, reads memory, writes an integer register, but is
+         nevertheless an SSE insn.  The insn is of the form
+         bbbbbbbb:bbbbbbbb:bbbbbbbb:mod ireg rm where mod indicates
+         memory (ie is not 11b) and ireg is the int reg written.  The
+         first 3 bytes are held in lit32[23:0] since there is
+         insufficient space elsewhere.  mod and rm are to be replaced
+         at codegen time by a reference to the Temp/RealReg holding
+         the address.  Arg1 holds this Temp/RealReg.  ireg is to be
+         replaced at codegen time by a reference to the relevant
+         RealReg in which the answer is to be written.  Arg2 holds
+         this Temp/RealReg.  Transfer to the destination reg is always
+         at size 4.  However the memory read can be at sizes 4 or 8
+         and so this is what the sz field holds.
+      */
+      SSE3ag_MemRd_RegWr,
+
       /* 5 bytes, no memrefs, no iregdefs, copy exactly to the
          output.  Held in val1[15:0], val2[15:0] and val3[7:0]. */
       SSE5,