]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Implement a few SSE instructions, enough to run bzip2 when compiled
authorJulian Seward <jseward@acm.org>
Sun, 25 May 2003 01:07:34 +0000 (01:07 +0000)
committerJulian Seward <jseward@acm.org>
Sun, 25 May 2003 01:07:34 +0000 (01:07 +0000)
with the Intel C compiler (7.1.009) with vectorisation for SSE engaged
(-xK).

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

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

index 2236a47d276cf8422396017ba1ff53b764efee76..9b8fb84d02cb23c2ac40329fefba591e3e948c2f 100644 (file)
@@ -1419,6 +1419,86 @@ static void emit_MMX2_regmem ( FlagSet uses_sflags,
                   nameIReg(4,ireg) );
 }
 
+static void emit_SSE2a ( FlagSet uses_sflags, 
+                         FlagSet sets_sflags,
+                         UChar first_byte, 
+                         UChar second_byte, 
+                        UChar third_byte,
+                         Int ireg )
+{
+   VG_(new_emit)(True, uses_sflags, sets_sflags);
+   VG_(emitB) ( first_byte );
+   VG_(emitB) ( second_byte );
+   third_byte &= 0x38; /* mask out mod and rm fields */
+   emit_amode_regmem_reg ( ireg, third_byte >> 3 );
+   if (dis)
+      VG_(printf)("\n\t\tsse-0x%x:0x%x:0x%x-(%s)\n", 
+                  (UInt)first_byte, (UInt)second_byte, (UInt)third_byte,
+                  nameIReg(4,ireg) );
+}
+
+static void emit_SSE3a ( FlagSet uses_sflags, 
+                         FlagSet sets_sflags,
+                         UChar first_byte, 
+                         UChar second_byte, 
+                        UChar third_byte,
+                        UChar fourth_byte,
+                         Int ireg )
+{
+   VG_(new_emit)(True, uses_sflags, sets_sflags);
+   VG_(emitB) ( first_byte );
+   VG_(emitB) ( second_byte );
+   VG_(emitB) ( third_byte );
+   fourth_byte &= 0x38; /* mask out mod and rm fields */
+   emit_amode_regmem_reg ( ireg, fourth_byte >> 3 );
+   if (dis)
+      VG_(printf)("\n\t\tsse-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_SSE3g ( FlagSet uses_sflags, 
+                         FlagSet sets_sflags,
+                         UChar first_byte, 
+                         UChar second_byte, 
+                        UChar third_byte,
+                        UChar fourth_byte,
+                         Int ireg )
+{
+   VG_(new_emit)(True, uses_sflags, sets_sflags);
+   VG_(emitB) ( first_byte );
+   VG_(emitB) ( second_byte );
+   VG_(emitB) ( third_byte );
+   fourth_byte &= 0x38; /* mask out mod and rm fields */
+   fourth_byte |= 0xC0; /* set top two bits: mod = 11b */
+   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) );
+}
+
+static void emit_SSE4 ( FlagSet uses_sflags, 
+                         FlagSet sets_sflags,
+                         UChar first_byte, 
+                         UChar second_byte, 
+                        UChar third_byte,
+                         UChar fourth_byte )
+{
+   VG_(new_emit)(True, uses_sflags, sets_sflags);
+   VG_(emitB) ( first_byte );
+   VG_(emitB) ( second_byte );
+   VG_(emitB) ( third_byte );
+   VG_(emitB) ( fourth_byte );
+   if (dis)
+      VG_(printf)("\n\t\tsse-0x%x:0x%x:0x%x:0x%x\n", 
+                  (UInt)first_byte, (UInt)second_byte, 
+                  (UInt)third_byte, (UInt)fourth_byte );
+}
+
 static void emit_MMX2_reg_to_mmxreg ( FlagSet uses_sflags, 
                                       FlagSet sets_sflags,
                                      UChar first_byte, 
@@ -3593,6 +3673,78 @@ static void emitUInstr ( UCodeBlock* cb, Int i,
                              u->val2 & 0xFF );
          break;
 
+      case SSE2a_MemWr:
+      case SSE2a_MemRd:
+         vg_assert(u->size == 4 || u->size == 16);
+         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;
+         }
+         emit_SSE2a ( u->flags_r, u->flags_w,
+                      (u->val1 >> 8) & 0xFF,
+                      u->val1 & 0xFF,
+                      u->val2 & 0xFF,
+                      u->val3 );
+         break;
+
+      case SSE3a_MemWr:
+      case SSE3a_MemRd:
+         vg_assert(u->size == 4 || u->size == 16);
+         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;
+         }
+         emit_SSE3a ( u->flags_r, u->flags_w,
+                      (u->val1 >> 8) & 0xFF,
+                      u->val1 & 0xFF,
+                      (u->val2 >> 8) & 0xFF,
+                      u->val2 & 0xFF,
+                      u->val3 );
+         break;
+
+      case SSE3g_RegRd:
+         vg_assert(u->size == 4);
+         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;
+         }
+         emit_SSE3g ( u->flags_r, u->flags_w,
+                      (u->val1 >> 8) & 0xFF,
+                      u->val1 & 0xFF,
+                      (u->val2 >> 8) & 0xFF,
+                      u->val2 & 0xFF,
+                      u->val3 );
+         break;
+
+      case SSE4:
+         vg_assert(u->size == 0);
+         vg_assert(u->tag1 == Lit16);
+         vg_assert(u->tag2 == Lit16);
+         vg_assert(u->tag3 == NoValue);
+         vg_assert(!anyFlagUse(u));
+         if (!(*sselive)) {
+            emit_get_sse_state();
+            *sselive = True;
+         }
+         emit_SSE4 ( u->flags_r, u->flags_w,
+                     (u->val1 >> 8) & 0xFF,
+                     u->val1 & 0xFF,
+                     (u->val2 >> 8) & 0xFF,
+                     u->val2 & 0xFF );
+         break;
+
       default: 
          if (VG_(needs).extended_UCode) {
            if (*sselive) {
index f138dc591d3e0e5d2395eb043ab1a5629a1941c1..d4548a942bbc721e6630e3f6eb32d009016b8923 100644 (file)
@@ -146,6 +146,14 @@ Char* VG_(name_of_mmx_reg) ( Int mmxreg )
    return mmx_names[mmxreg];
 }
 
+Char* VG_(name_of_xmm_reg) ( Int xmmreg )
+{
+   static Char* xmm_names[8] 
+     = { "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7" };
+   if (xmmreg < 0 || xmmreg > 7) VG_(core_panic)("name_of_xmm_reg");
+   return xmm_names[xmmreg];
+}
+
 Char* VG_(name_of_mmx_gran) ( UChar gran )
 {
    switch (gran) {
@@ -3247,11 +3255,48 @@ Addr dis_MMXop_regmem_to_reg ( UCodeBlock* cb,
 }
 
 
+
+/* Simple SSE operations, either 
+       op   (src)xmmreg, (dst)xmmreg
+   or
+       op   (src)address, (dst)xmmreg
+   It is assumed that there are 3 opcode bytes preceding the start
+   of the address mode.  eip points to the first opcode byte.
+*/
+static
+Addr dis_SSE3_reg_or_mem ( UCodeBlock* cb, 
+                           UChar sorb, 
+                           Char* name, 
+                           Int sz, 
+                           Addr eip )
+{
+   UChar opc1 = getUChar(eip); 
+   UChar opc2 = getUChar(eip+1);
+   UChar opc3 = getUChar(eip+2);
+   UChar modrm = getUChar(eip+3);
+   eip += 3;
+   if (epartIsReg(modrm)) {
+      /* Completely internal SSE insn. */
+      uInstr2(cb, SSE4, 0,  /* ignore sz for internal ops */
+                  Lit16, (((UShort)opc1) << 8) | (UShort)opc2,
+                  Lit16, (((UShort)opc3) << 8) | (UShort)modrm );
+      if (dis)
+         VG_(printf)("%s %s, %s\n", name, 
+                     nameXMMReg(eregOfRM(modrm)), nameXMMReg(gregOfRM(modrm)) );
+         eip++;
+   } else {
+      VG_(core_panic)("dis_SSE3_reg_or_mem: mem");
+   }
+   return eip;
+}
+
+
+
 /*------------------------------------------------------------*/
 /*--- Disassembling entire basic blocks                    ---*/
 /*------------------------------------------------------------*/
 
-/* Disassemble a single instruction into ucode, returning the update
+/* Disassemble a single instruction into ucode, returning the updated
    eip, and setting *isEnd to True if this is the last insn in a basic
    block.  Also do debug printing if (dis). */
 
@@ -3339,9 +3384,107 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
          break;
    }
 
+   /* ---------------------------------------------------- */
+   /* --- The SSE/SSE2 decoder.                        --- */
+   /* ---------------------------------------------------- */
+
+   /* If it looks like this CPU might support SSE, try decoding SSE
+      insns.  */
+   if (VG_(have_ssestate)) {
+   UChar* insn = (UChar*)eip;
+
+   /* STMXCSR/LDMXCSR m32 */
+   if (insn[0] == 0x0F && insn[1] == 0xAE 
+       && (gregOfRM(insn[2]) == 3 || gregOfRM(insn[2]) == 2) ) {
+      Bool store = gregOfRM(insn[2]) == 3;
+      pair = disAMode ( cb, sorb, eip+2, dis?dis_buf:NULL );
+      t1   = LOW24(pair);
+      eip += 2+HI8(pair);
+      uInstr3(cb, store ? SSE2a_MemWr : SSE2a_MemRd, 4,
+                  Lit16, (((UShort)insn[0]) << 8) | (UShort)insn[1],
+                  Lit16, (UShort)insn[2],
+                  TempReg, t1 );
+      if (dis)
+         VG_(printf)("%smxcsr %s\n", store ? "st" : "ld", dis_buf );
+      goto sse_done;
+   }
+
+   /* CVTSI2SS */
+   if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x2A) {
+      modrm = insn[3];
+      t1 = newTemp(cb);
+      if (epartIsReg(modrm)) { 
+         uInstr2(cb, GET, 4, ArchReg, eregOfRM(modrm), TempReg, t1);
+         uInstr3(cb, SSE3g_RegRd, 4,
+                     Lit16, (((UShort)insn[0]) << 8) | (UShort)insn[1],
+                     Lit16, (((UShort)insn[2]) << 8) | (UShort)insn[3],
+                     TempReg, t1 );
+         eip += 4;
+        if (dis)
+            VG_(printf)("cvtsi2ss %s, %s\n", nameIReg(4,eregOfRM(modrm)), 
+                                             nameXMMReg(gregOfRM(modrm)));
+      } else {
+         pair = disAMode ( cb, sorb, eip+3, dis?dis_buf:NULL );
+         t2   = LOW24(pair);
+         eip += 3+HI8(pair);
+        uInstr2(cb, LOAD, 4, TempReg, t2, TempReg, t1);
+         uInstr3(cb, SSE3g_RegRd, 4,
+                     Lit16, (((UShort)insn[0]) << 8) | (UShort)insn[1],
+                     Lit16, (((UShort)insn[2]) << 8) | (UShort)insn[3],
+                     TempReg, t1 );
+        if (dis)
+            VG_(printf)("cvtsi2ss %s, %s\n", dis_buf,
+                                             nameXMMReg(gregOfRM(modrm)));
+      }
+      goto sse_done;
+   }
+
+   /* DIVSS */
+   if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x5E) {
+      eip = dis_SSE3_reg_or_mem ( cb, sorb, "divss", 4, eip );
+      goto sse_done;
+   }
+
+   /* MOVSS */
+   if (insn[0] == 0xF3 && insn[1] == 0x0F && insn[2] == 0x11) {
+      if (epartIsReg(insn[3])) {
+         /* MOVSS xmm, xmm */
+         VG_(core_panic)("MOVSS reg");
+         eip = dis_SSE3_reg_or_mem ( cb, sorb, "movss", 4, eip );
+      } else {
+         Bool store = insn[2] == 0x11;
+         pair = disAMode ( cb, sorb, eip+3, dis?dis_buf:NULL );
+         t1   = LOW24(pair);
+         eip += 3+HI8(pair);
+         uInstr3(cb, store ? SSE3a_MemWr : SSE3a_MemRd, 4,
+                     Lit16, (((UShort)insn[0]) << 8) | (UShort)insn[1],
+                     Lit16, (((UShort)insn[2]) << 8) | (UShort)insn[3],
+                     TempReg, t1 );
+         if (dis && store)
+            VG_(printf)("movss %s, %s\n", 
+                        nameXMMReg(gregOfRM(insn[3])), dis_buf );
+         if (dis && !store)
+            VG_(printf)("movss %s, %s\n", 
+                        dis_buf, nameXMMReg(gregOfRM(insn[3])) );
+      }
+      goto sse_done;
+   }
+
+   /* Fall through into the non-SSE decoder. */
 
+   } /* if (VG_(have_ssestate)) */
+
+
+   /* ---------------------------------------------------- */
+   /* --- end of the SSE/SSE2 decoder.                 --- */
+   /* ---------------------------------------------------- */
+
+   /* Get the primary opcode. */
    opc = getUChar(eip); eip++;
 
+   /* We get here if the current insn isn't SSE, or this CPU doesn't
+      support SSE. */
+
    switch (opc) {
 
    /* ------------------------ Control flow --------------- */
@@ -3705,7 +3848,7 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
       handleSegOverride(cb, sorb, t2);
       uInstr2(cb, LOAD, sz, TempReg, t2,  TempReg, t1);
       uInstr2(cb, PUT,  sz, TempReg, t1,  ArchReg, R_EAX);
-      if (dis) VG_(printf)("mov%c %s0x%x,%s\n", nameISize(sz), 
+      if (dis) VG_(printf)("mov%c %s0x%x, %s\n", nameISize(sz), 
                            sorbTxt(sorb),
                            d32, nameIReg(sz,R_EAX));
       break;
@@ -3721,9 +3864,9 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
       uLiteral(cb, d32);
       handleSegOverride(cb, sorb, t2);
       uInstr2(cb, STORE, sz, TempReg, t1,    TempReg, t2);
-      if (dis) VG_(printf)("mov%c %s,%s0x%x\n", nameISize(sz), 
-                           sorbTxt(sorb),
-                           nameIReg(sz,R_EAX), d32);
+      if (dis) VG_(printf)("mov%c %s, %s0x%x\n", nameISize(sz), 
+                           nameIReg(sz,R_EAX),
+                           sorbTxt(sorb), d32);
       break;
 
    case 0xB0: /* MOV imm,AL */
@@ -4316,7 +4459,8 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
          if (dis) VG_(printf)("repe nop (P4 pause)\n");
          /* do nothing; apparently a hint to the P4 re spin-wait loop */
       } else {
-         VG_(printf)("REPE then 0x%x\n", (UInt)abyte);
+         VG_(printf)("Insn bytes: 0xF3 0x%x 0x%x\n", 
+                     (UInt)abyte, (UInt)getUChar(eip));
          VG_(core_panic)("Unhandled REPE case");
       }
       break;
@@ -5105,6 +5249,7 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
       VG_(core_panic)("unhandled x86 opcode");
    }
 
+  sse_done:
    if (dis)
       VG_(printf)("\n");
    for (; first_uinstr < cb->used; first_uinstr++) {
index 0010807602f9c3a6be0a55c290ba14f272b10770..9c2445f1e3c6cadbeea6139648064bee58d1555a 100644 (file)
@@ -411,6 +411,7 @@ Bool VG_(saneUInstr) ( Bool beforeRA, Bool beforeLiveness, UInstr* u )
 #  define SZ0  (u->size == 0)
 #  define SZ42 (u->size == 4 || u->size == 2)
 #  define SZ48 (u->size == 4 || u->size == 8)
+#  define SZ416 (u->size == 4 || u->size == 16)
 #  define SZi  (u->size == 4 || u->size == 2 || u->size == 1)
 #  define SZf  (  u->size ==  4 || u->size ==  8 || u->size ==   2     \
                || u->size == 10 || u->size == 28 || u->size == 108)
@@ -454,6 +455,7 @@ Bool VG_(saneUInstr) ( Bool beforeRA, Bool beforeLiveness, UInstr* u )
 #  define L1  (u->tag1 == Literal && u->val1 == 0)
 #  define L2  (u->tag2 == Literal && u->val2 == 0)
 #  define Ls1 (u->tag1 == Lit16)
+#  define Ls2 (u->tag2 == Lit16)
 #  define Ls3 (u->tag3 == Lit16)
 #  define TRL1 (TR1 || L1)
 #  define TRAL1 (TR1 || A1 || L1)
@@ -548,11 +550,19 @@ Bool VG_(saneUInstr) ( Bool beforeRA, Bool beforeLiveness, UInstr* u )
    /* Fields checked:     lit32   size  flags_r/w tag1   tag2   tag3    (rest) */
    case MMX1:
    case MMX2:       return LIT0 && SZ0  && CC0 &&  Ls1 &&  N2 &&  N3 && XOTHER;
-   case MMX3:       return LIT0 && SZ0  && CC0 &&  Ls1 && Ls1 &&  N3 && XOTHER;
+   case MMX3:       return LIT0 && SZ0  && CC0 &&  Ls1 && Ls2 &&  N3 && XOTHER;
    case MMX2_MemRd: return LIT0 && SZ48 && CC0 &&  Ls1 && TR2 &&  N3 && XOTHER;
    case MMX2_MemWr: return LIT0 && SZ48 && CC0 &&  Ls1 && TR2 &&  N3 && XOTHER;
    case MMX2_RegRd: return LIT0 && SZ4  && CC0 &&  Ls1 && TR2 &&  N3 && XOTHER;
    case MMX2_RegWr: return LIT0 && SZ4  && CC0 &&  Ls1 && TR2 &&  N3 && XOTHER;
+
+   /* Fields checked:        lit32   size  flags_r/w tag1   tag2   tag3    (rest) */
+   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 && SZ416 && CC0  && Ls1 && Ls2 && TR3 && XOTHER;
+   case SSE3a_MemRd:  return LIT0 && SZ416 && CC0  && Ls1 && Ls2 && TR3 && XOTHER;
+   case SSE3g_RegRd:  return LIT0 && SZ4   && CC0  && Ls1 && Ls2 && TR3 && XOTHER;
+   case SSE4:         return LIT0 && SZ0   && CC0  && Ls1 && Ls2 && N3  && XOTHER;
    default: 
       if (VG_(needs).extended_UCode)
          return SK_(sane_XUInstr)(beforeRA, beforeLiveness, u);
@@ -573,6 +583,7 @@ Bool VG_(saneUInstr) ( Bool beforeRA, Bool beforeLiveness, UInstr* u )
 #  undef SZ0
 #  undef SZ42
 #  undef SZ48
+#  undef SZ416
 #  undef SZi
 #  undef SZf
 #  undef SZ4m
@@ -600,6 +611,7 @@ Bool VG_(saneUInstr) ( Bool beforeRA, Bool beforeLiveness, UInstr* u )
 #  undef L1
 #  undef L2
 #  undef Ls1
+#  undef Ls2
 #  undef Ls3
 #  undef TRL1
 #  undef TRAL1
@@ -861,6 +873,12 @@ Char* VG_(name_UOpcode) ( Bool upper, Opcode opc )
       case MMX2_MemWr: return "MMX2_MWr" ;
       case MMX2_RegRd: return "MMX2_RRd" ;
       case MMX2_RegWr: return "MMX2_RWr" ;
+      case SSE2a_MemWr: return "SSE2a_MWr";
+      case SSE2a_MemRd: return "SSE2a_MRd";
+      case SSE3g_RegRd: return "SSE3g_RRd";
+      case SSE4:        return "SSE4";
+      case SSE3a_MemWr: return "SSE3a_MWr";
+      case SSE3a_MemRd: return "SSE3a_MRd";
       default:
          if (VG_(needs).extended_UCode)
             return SK_(name_XUOpcode)(opc);
@@ -930,20 +948,23 @@ void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness )
       case 2:  VG_(printf)("W"); break;
       case 4:  VG_(printf)("L"); break;
       case 8:  VG_(printf)("Q"); break;
+      case 16: VG_(printf)("QQ"); break;
       default: VG_(printf)("%d", (Int)u->size); break;
    }
 
+   VG_(printf)("       \t");
+
    switch (u->opcode) {
 
       case CALLM_S: case CALLM_E:
          break;
 
       case INCEIP:
-         VG_(printf)("\t$%d", u->val1);
+         VG_(printf)("$%d", u->val1);
          break;
 
       case LEA2:
-         VG_(printf)("\t%d(" , u->lit32);
+         VG_(printf)("%d(" , u->lit32);
          VG_(pp_UOperand)(u, 1, 4, False);
          VG_(printf)(",");
          VG_(pp_UOperand)(u, 2, 4, False);
@@ -952,7 +973,7 @@ void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness )
          break;
 
       case LEA1:
-         VG_(printf)("\t%d" , u->lit32);
+         VG_(printf)("%d" , u->lit32);
          VG_(pp_UOperand)(u, 1, 4, True);
          VG_(printf)(", ");
          VG_(pp_UOperand)(u, 2, 4, False);
@@ -962,55 +983,82 @@ void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness )
          break;
 
       case FPU_W:
-         VG_(printf)("\t0x%x:0x%x, ",
+         VG_(printf)("0x%x:0x%x, ",
                      (u->val1 >> 8) & 0xFF, u->val1 & 0xFF );
          VG_(pp_UOperand)(u, 2, 4, True);
          break;
 
       case FPU_R:
-         VG_(printf)("\t");
+         VG_(printf)("");
          VG_(pp_UOperand)(u, 2, 4, True);
          VG_(printf)(", 0x%x:0x%x",
                      (u->val1 >> 8) & 0xFF, u->val1 & 0xFF );
          break;
 
       case FPU:
-         VG_(printf)("\t0x%x:0x%x",
+         VG_(printf)("0x%x:0x%x",
                      (u->val1 >> 8) & 0xFF, u->val1 & 0xFF );
          break;
 
       case MMX1:
-         VG_(printf)("\t0x%x",
+         VG_(printf)("0x%x",
                      u->val1 & 0xFF );
          break;
 
       case MMX2:
-         VG_(printf)("\t0x%x:0x%x",
+         VG_(printf)("0x%x:0x%x",
                      (u->val1 >> 8) & 0xFF, u->val1 & 0xFF );
          break;
 
       case MMX3:
-         VG_(printf)("\t0x%x:0x%x:0x%x",
+         VG_(printf)("0x%x:0x%x:0x%x",
                      (u->val1 >> 8) & 0xFF, u->val1 & 0xFF, u->val2 & 0xFF );
          break;
 
       case MMX2_RegWr:
       case MMX2_RegRd:
-         VG_(printf)("\t0x%x:0x%x, ",
+         VG_(printf)("0x%x:0x%x, ",
                      (u->val1 >> 8) & 0xFF, u->val1 & 0xFF );
          VG_(pp_UOperand)(u, 2, 4, False);
          break;
  
       case MMX2_MemWr:
       case MMX2_MemRd:
-          VG_(printf)("\t0x%x:0x%x",
+          VG_(printf)("0x%x:0x%x",
                      (u->val1 >> 8) & 0xFF, u->val1 & 0xFF );
          VG_(pp_UOperand)(u, 2, 4, True);
          break;
 
+      case SSE2a_MemWr:
+      case SSE2a_MemRd:
+         VG_(printf)("0x%x:0x%x:0x%x",
+                     (u->val1 >> 8) & 0xFF, u->val1 & 0xFF, u->val2 & 0xFF );
+         VG_(pp_UOperand)(u, 3, 4, True);
+         break;
+
+      case SSE3a_MemWr:
+      case SSE3a_MemRd:
+         VG_(printf)("0x%x:0x%x:0x%x:0x%x",
+                     (u->val1 >> 8) & 0xFF, u->val1 & 0xFF, 
+                     (u->val1 >> 8) & 0xFF, u->val2 & 0xFF );
+         VG_(pp_UOperand)(u, 3, 4, True);
+         break;
+
+      case SSE3g_RegRd:
+         VG_(printf)("0x%x:0x%x:0x%x:0x%x",
+                     (u->val1 >> 8) & 0xFF, u->val1 & 0xFF, 
+                     (u->val2 >> 8) & 0xFF, u->val2 & 0xFF );
+         VG_(pp_UOperand)(u, 3, 4, True);
+         break;
+
+      case SSE4:
+         VG_(printf)("0x%x:0x%x:0x%x:0x%x",
+                     (u->val1 >> 8) & 0xFF, u->val1 & 0xFF, 
+                     (u->val2 >> 8) & 0xFF, u->val2 & 0xFF );
+         break;
+
       case GET: case PUT: case MOV: case LOAD: case STORE: case CMOV:
       case GETSEG: case PUTSEG:
-         VG_(printf)("\t");
          VG_(pp_UOperand)(u, 1, u->size, u->opcode==LOAD); 
          VG_(printf)(", ");
          VG_(pp_UOperand)(u, 2, u->size, u->opcode==STORE);
@@ -1024,7 +1072,6 @@ void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness )
             case JmpClientReq: VG_(printf)("-cli"); break;
             default: break;
          }
-         VG_(printf)("\t");
          VG_(pp_UOperand)(u, 1, u->size, False);
          if (CondAlways == u->cond) {
             /* Print x86 instruction size if filled in */
@@ -1036,13 +1083,11 @@ void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness )
       case GETF: case PUTF:
       case CC2VAL: case PUSH: case POP: case CLEAR: case CALLM:
       case NOT: case NEG: case INC: case DEC: case BSWAP:
-         VG_(printf)("\t");
          VG_(pp_UOperand)(u, 1, u->size, False);
          break;
 
       /* Print a "(s)" after args passed on stack */
       case CCALL:
-         VG_(printf)("\t");
          if (u->has_ret_val) {
             VG_(pp_UOperand)(u, 3, 0, False);
             VG_(printf)(" = ");
@@ -1074,7 +1119,6 @@ void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness )
       case XOR: case SUB: case SBB:   
       case SHL: case SHR: case SAR: 
       case ROL: case ROR: case RCL: case RCR:   
-         VG_(printf)("\t");
          VG_(pp_UOperand)(u, 1, u->size, False); 
          VG_(printf)(", ");
          VG_(pp_UOperand)(u, 2, u->size, False);
@@ -1083,7 +1127,6 @@ void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness )
       case WIDEN:
          VG_(printf)("_%c%c", VG_(toupper)(nameISize(u->extra4b)),
                               u->signed_widen?'s':'z');
-         VG_(printf)("\t");
          VG_(pp_UOperand)(u, 1, u->size, False);
          break;
 
@@ -1159,9 +1202,16 @@ Int VG_(get_reg_usage) ( UInstr* u, Tag tag, Int* regs, Bool* isWrites )
       case LEA1: RD(1); WR(2); break;
       case LEA2: RD(1); RD(2); WR(3); break;
 
+      case SSE3g_RegRd:
+      case SSE3a_MemWr:
+      case SSE3a_MemRd:
+      case SSE2a_MemWr: 
+      case SSE2a_MemRd: RD(3);
+
       case MMX2_RegRd: RD(2); break;
       case MMX2_RegWr: WR(2); break;
 
+      case SSE4:
       case MMX1: case MMX2: case MMX3:
       case NOP:   case FPU:   case INCEIP: case CALLM_S: case CALLM_E:
       case CLEAR: case CALLM: case LOCK: break;
@@ -1313,6 +1363,10 @@ Int maybe_uinstrReadsArchReg ( UInstr* u )
       case MMX1: case MMX2: case MMX3:
       case MMX2_MemRd: case MMX2_MemWr:
       case MMX2_RegRd: case MMX2_RegWr:
+      case SSE2a_MemWr: case SSE2a_MemRd:
+      case SSE3a_MemWr: case SSE3a_MemRd:
+      case SSE3g_RegRd:
+      case SSE4:
       case WIDEN:
       /* GETSEG and USESEG are to do with ArchRegS, not ArchReg */
       case GETSEG: case PUTSEG: 
@@ -1441,6 +1495,9 @@ static void vg_improve ( UCodeBlock* cb )
                if (cb->instrs[m].tag2 == TempReg 
                    && cb->instrs[m].val2 == tr) 
                  cb->instrs[m].val2 = told;
+               if (cb->instrs[m].tag3 == TempReg 
+                   && cb->instrs[m].val3 == tr) 
+                 cb->instrs[m].val3 = told;
             }
             BIND_ARCH_TO_TEMP(ar,told);
          }
@@ -1577,6 +1634,9 @@ static void vg_improve ( UCodeBlock* cb )
             if (cb->instrs[j].tag2 == TempReg 
                 && cb->instrs[j].val2 == u->val2)
                cb->instrs[j].val2 = u->val1;
+            if (cb->instrs[j].tag3 == TempReg 
+                && cb->instrs[j].val3 == u->val2)
+               cb->instrs[j].val3 = u->val1;
          }
          last_live_before[u->val1] = last_live_before[u->val2];
          last_live_before[u->val2] = i-1;
index 6dd05ccb8c1ef78230d3bae39f6d20d4606e64a7..e71d342e7d23180ef011c1fb6bcbaf793350f695 100644 (file)
@@ -572,8 +572,8 @@ typedef
       /* ------------ SSE/SSE2 ops ------------ */
       /* In the following:
 
-         a digit N indicates the next N bytes are to be copied exactly to the
-         output.
+         a digit N indicates the next N bytes are to be copied exactly
+         to the output.
 
          'a' indicates a mod-xmmreg-rm byte, where the mod-rm part is
          to be replaced at codegen time to a Temp/RealReg holding the
@@ -596,7 +596,7 @@ typedef
          Held in val1[15:0] and val2[7:0], and mod and rm are to be
          replaced at codegen time by a reference to the Temp/RealReg
          holding the address.  Arg3 holds this Temp/Real Reg.
-         Transfer is always at size 16.  */
+         Transfer is usually, but not always, at size 16.  */
       SSE2a_MemRd,
       SSE2a_MemWr,
 
@@ -631,12 +631,12 @@ typedef
       SSE3g_RegWr,
 
       /* 4 bytes, reads an integer register.  Insns of the form
-         bbbbbbbb:bbbbbbbb:bbbbbbbb:11 ireg xmmreg.
+         bbbbbbbb:bbbbbbbb:bbbbbbbb:11 xmmreg ireg.
          Held in val1[15:0] and val2[15:0], and ireg is to be replaced
          at codegen time by a reference to the relevant RealReg.
          Transfer is always at size 4.  Arg3 holds this Temp/Real Reg.
       */
-      SSE3h_RegRd,
+      SSE3g_RegRd,
 
       /* 5 bytes, no memrefs, no iregdefs, copy exactly to the
          output.  Held in val1[15:0], val2[15:0] and val3[7:0]. */
@@ -1082,6 +1082,7 @@ extern Char  VG_(name_of_int_size) ( Int size );
 #define nameSReg    VG_(name_of_seg_reg)
 #define nameMMXReg  VG_(name_of_mmx_reg)
 #define nameMMXGran VG_(name_of_mmx_gran)
+#define nameXMMReg  VG_(name_of_xmm_reg)
 
 /* Randomly useful things */
 extern UInt  VG_(extend_s_8to32) ( UInt x );