]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
More SSE instructions.
authorJulian Seward <jseward@acm.org>
Sat, 14 Jun 2003 13:22:36 +0000 (13:22 +0000)
committerJulian Seward <jseward@acm.org>
Sat, 14 Jun 2003 13:22:36 +0000 (13:22 +0000)
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@1690

coregrind/vg_from_ucode.c
coregrind/vg_to_ucode.c
coregrind/vg_translate.c

index 2c60eb74b08958a3bc2fc9cf1f7292dbff148d2c..af63fa22f4ed7b31c909917bbe748566e1873bf8 100644 (file)
@@ -1580,6 +1580,27 @@ static void emit_SSE4 ( FlagSet uses_sflags,
                   (UInt)third_byte, (UInt)fourth_byte );
 }
 
+static void emit_SSE5 ( FlagSet uses_sflags, 
+                         FlagSet sets_sflags,
+                         UChar first_byte, 
+                         UChar second_byte, 
+                        UChar third_byte,
+                        UChar fourth_byte,
+                        UChar fifth_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 );
+   VG_(emitB) ( fifth_byte );
+   if (dis)
+      VG_(printf)("\n\t\tsse-0x%x:0x%x:0x%x:0x%x:0x%x\n", 
+                  (UInt)first_byte, (UInt)second_byte, 
+                  (UInt)third_byte, (UInt)fourth_byte,
+                  (UInt)fifth_byte );
+}
+
 static void emit_SSE3 ( FlagSet uses_sflags, 
                          FlagSet sets_sflags,
                          UChar first_byte, 
@@ -3872,6 +3893,24 @@ static void emitUInstr ( UCodeBlock* cb, Int i,
                              u->val3 );
          break;
 
+      case SSE5:
+         vg_assert(u->size == 0);
+         vg_assert(u->tag1 == Lit16);
+         vg_assert(u->tag2 == Lit16);
+         vg_assert(u->tag3 == Lit16);
+         vg_assert(!anyFlagUse(u));
+         if (!(*sselive)) {
+            emit_get_sse_state();
+            *sselive = True;
+         }
+         emit_SSE5 ( u->flags_r, u->flags_w,
+                     (u->val1 >> 8) & 0xFF,
+                     u->val1 & 0xFF,
+                     (u->val2 >> 8) & 0xFF,
+                     u->val2 & 0xFF,
+                     u->val3 & 0xFF );
+         break;
+
       case SSE4:
          vg_assert(u->size == 0);
          vg_assert(u->tag1 == Lit16);
index c0f11fe878adcf0dcefc0638843da93d97e8b3e3..a87bd65e527c2eca1b1227385af9304d8a7b25d4 100644 (file)
@@ -3394,6 +3394,45 @@ Addr dis_SSE2_reg_or_mem_Imm8 ( UCodeBlock* cb,
 }
 
 
+/* Simple SSE operations, either 
+       op   (src)xmmreg, (dst)xmmreg
+   or
+       op   (src)address, (dst)xmmreg
+   3 opcode bytes and an 8-bit immediate after the amode.
+   Supplied eip points to the first address mode byte.
+*/
+static
+Addr dis_SSE3_reg_or_mem_Imm8 ( UCodeBlock* cb, 
+                                UChar sorb, 
+                               Addr eip,
+                                Int sz, 
+                                Char* name,
+                               UChar opc1, 
+                               UChar opc2,
+                                UChar opc3 )
+{
+   UChar modrm = getUChar(eip);
+   UChar imm8;
+   if (epartIsReg(modrm)) {
+      /* Completely internal SSE insn. */
+      eip++;
+      imm8 = getUChar(eip);
+      uInstr3(cb, SSE5, 0,  /* ignore sz for internal ops */
+                  Lit16, (((UShort)opc1) << 8) | (UShort)opc2,
+                  Lit16, (((UShort)opc3) << 8) | (UShort)modrm,
+                  Lit16, (UShort)imm8 );
+      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_Imm8: mem");
+   }
+   return eip;
+}
+
+
 /* Disassemble an SSE insn which is either a simple reg-reg move or a
    move between registers and memory.  Supplied eip points to the
    first address mode byte.
@@ -3734,6 +3773,15 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
       goto decode_success;
    }
 
+   /* PSHUFD */
+   if (sz == 2
+       && insn[0] == 0x0F && insn[1] == 0x70) {
+      eip = dis_SSE3_reg_or_mem_Imm8 ( cb, sorb, eip+2, 16, 
+                                           "pshufd",
+                                           0x66, insn[0], insn[1] );
+      goto decode_success;
+   }
+
    /* SHUFPS */
    if (insn[0] == 0x0F && insn[1] == 0xC6) {
       vg_assert(sz == 4);
@@ -3766,7 +3814,6 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
       goto decode_success;
    }
 
-#if 0
    /* SUBSD */
    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x5C) {
       vg_assert(sz == 4);
@@ -3774,7 +3821,6 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
                                       insn[0], insn[1], insn[2] );
       goto decode_success;
    }
-#endif
 
    /* ADDSD */
    if (insn[0] == 0xF2 && insn[1] == 0x0F && insn[2] == 0x58) {
@@ -3800,11 +3846,29 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
       goto decode_success;
    }
 
+   /* PAND (src)xmmreg-or-mem, (dst)xmmreg */
+   if (sz == 2
+       && insn[0] == 0x0F && insn[1] == 0xDB) {
+      eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "pand",
+                                      0x66, insn[0], insn[1] );
+      goto decode_success;
+   }
+
+   /* POR (src)xmmreg-or-mem, (dst)xmmreg */
+   if (sz == 2
+       && insn[0] == 0x0F && insn[1] == 0xEB) {
+      eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "por",
+                                      0x66, insn[0], insn[1] );
+      goto decode_success;
+   }
+
    /* PUNPCKLgg (src)xmmreg-or-mem, (dst)xmmreg */
    /* 60 is BW, 61 is WD, 62 is DQ */
    if (sz == 2
-       && insn[0] == 0x0F && insn[1] == 0x62) {
-      eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, "punpckldq",
+       && insn[0] == 0x0F 
+       && (insn[1] == 0x61 || insn[1] == 0x62)) {
+      eip = dis_SSE3_reg_or_mem ( cb, sorb, eip+2, 16, 
+                                      "punpckl{bw,wd,dq}",
                                       0x66, insn[0], insn[1] );
       goto decode_success;
    }
@@ -3863,10 +3927,25 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
       goto decode_success;
    }
 
-   /* MOVAPS (28,29) -- aligned load/store of XMM reg, or x-x reg
+   /* I don't understand how MOVAPD differs from MOVAPS. */
+   /* MOVAPD (28,29) -- aligned load/store of xmm reg, or xmm-xmm reg
       move */
-   /* MOVUPS (10,11) -- unaligned load/store of XMM reg, or x-x reg
+   if (sz == 2
+       && insn[0] == 0x0F && insn[1] == 0x28) {
+      UChar* name = "movapd";
+                    //(insn[1] == 0x10 || insn[1] == 0x11)
+                    // ? "movups" : "movaps";
+      Bool store = False; //insn[1] == 0x29 || insn[1] == 11;
+      eip = dis_SSE3_load_store_or_mov
+               ( cb, sorb, eip+2, 16, store, name,
+                     0x66, insn[0], insn[1] );
+      goto decode_success;
+   }
+
+   /* MOVAPS (28,29) -- aligned load/store of xmm reg, or xmm-xmm reg
       move */
+   /* MOVUPS (10,11) -- unaligned load/store of xmm reg, or xmm-xmm
+      reg move */
    if (insn[0] == 0x0F && (insn[1] == 0x28
                            || insn[1] == 0x29
                            || insn[1] == 0x10
@@ -5412,35 +5491,55 @@ static Addr disInstr ( UCodeBlock* cb, Addr eip, Bool* isEnd )
          break;
 
       case 0x71: case 0x72: case 0x73: 
-         /* PSLL/PSRA/PSRL mmxreg by imm8 */
+         /* (sz==4): PSLL/PSRA/PSRL mmxreg by imm8 */
+         /* (sz==2): PSLL/PSRA/PSRL xmmreg by imm8 */
          {
-         UChar byte1, byte2, byte3, subopc, mmxreg;
-         vg_assert(sz == 4);
-         byte1 = opc;
-         byte2 = getUChar(eip); eip++;
-         byte3 = getUChar(eip); eip++;
-         mmxreg = byte2 & 7;
+         UChar byte1, byte2, byte3, subopc, mmreg;
+         vg_assert(sz == 4 || sz == 2);
+         byte1 = opc;                   /* 0x71/72/73 */
+         byte2 = getUChar(eip); eip++;  /* amode / sub-opcode */
+         byte3 = getUChar(eip); eip++;  /* imm8 */
+         mmreg = byte2 & 7;
          subopc = (byte2 >> 3) & 7;
          if (subopc == 2 || subopc == 6 || subopc == 4) {  
             /* 2 == 010 == SRL, 6 == 110 == SLL, 4 == 100 == SRA */
             /* ok */
          } else {
-            eip -= 2;
+            eip -= (sz==2 ? 3 : 2);
             goto decode_failure;
          }
-         uInstr2(cb, MMX3, 0, 
-                     Lit16, (((UShort)byte1) << 8) | ((UShort)byte2),
-                     Lit16, ((UShort)byte3) );
-         if (dis)
-            VG_(printf)("ps%s%s $%d, %s\n",
-                        (subopc == 2 ? "rl" 
-                         : subopc == 6 ? "ll" 
-                         : subopc == 4 ? "ra"
-                         : "??"),
-                        nameMMXGran(opc & 3),
-                        (Int)byte3,
-                        nameMMXReg(mmxreg) );
-         }
+         if (sz == 4) {
+            /* The leading 0x0F is implied for MMX*, so we don't
+              include it. */
+            uInstr2(cb, MMX3, 0, 
+                        Lit16, (((UShort)byte1) << 8) | ((UShort)byte2),
+                        Lit16, ((UShort)byte3) );
+            if (dis)
+               VG_(printf)("ps%s%s $%d, %s\n",
+                           (subopc == 2 ? "rl" 
+                            : subopc == 6 ? "ll" 
+                            : subopc == 4 ? "ra"
+                            : "??"),
+                           nameMMXGran(opc & 3),
+                           (Int)byte3,
+                           nameMMXReg(mmreg) );
+        } else {
+            /* Whereas we have to include it for SSE. */
+            uInstr3(cb, SSE5, 0, 
+                        Lit16, (((UShort)0x66) << 8) | ((UShort)0x0F),
+                        Lit16, (((UShort)byte1) << 8) | ((UShort)byte2),
+                        Lit16, ((UShort)byte3) );
+            if (dis)
+               VG_(printf)("ps%s%s $%d, %s\n",
+                           (subopc == 2 ? "rl" 
+                            : subopc == 6 ? "ll" 
+                            : subopc == 4 ? "ra"
+                            : "??"),
+                           nameMMXGran(opc & 3),
+                           (Int)byte3,
+                           nameXMMReg(mmreg) );
+        }
+        }
          break;
 
       case 0x77: /* EMMS */
index 6de24737c715ee78de18fc3a541572914e012877..f07bb0ee9ada2fa83bd3c2af03894a8e5781a774 100644 (file)
@@ -569,6 +569,7 @@ Bool VG_(saneUInstr) ( Bool beforeRA, Bool beforeLiveness, UInstr* u )
    case SSE3g1_RegRd: return LIT8 && SZ2   && CC0  && Ls1 && Ls2 && TR3 && XOTHER;
    case SSE3:         return LIT0 && SZ0   && CC0  && Ls1 && Ls2 && N3  && XOTHER;
    case SSE4:         return LIT0 && SZ0   && CCf  && Ls1 && Ls2 && N3  && XOTHER;
+   case SSE5:         return LIT0 && SZ0   && CC0  && Ls1 && Ls2 && Ls3 && XOTHER;
    default: 
       if (VG_(needs).extended_UCode)
          return SK_(sane_XUInstr)(beforeRA, beforeLiveness, u);
@@ -889,6 +890,7 @@ Char* VG_(name_UOpcode) ( Bool upper, Opcode opc )
       case SSE3g1_RegRd: return "SSE3g1_RRd";
       case SSE3:        return "SSE3";
       case SSE4:        return "SSE4";
+      case SSE5:        return "SSE5";
       case SSE3a_MemWr: return "SSE3a_MWr";
       case SSE3a_MemRd: return "SSE3a_MRd";
       default:
@@ -1085,6 +1087,13 @@ void pp_UInstrWorker ( Int instrNo, UInstr* u, Bool ppRegsLiveness )
                      (u->val2 >> 8) & 0xFF, u->val2 & 0xFF );
          break;
 
+      case SSE5:
+         VG_(printf)("0x%x:0x%x:0x%x:0x%x:0x%x",
+                     (u->val1 >> 8) & 0xFF, u->val1 & 0xFF, 
+                     (u->val2 >> 8) & 0xFF, u->val2 & 0xFF,
+                     u->val3 & 0xFF );
+         break;
+
       case GET: case PUT: case MOV: case LOAD: case STORE: case CMOV:
       case GETSEG: case PUTSEG:
          VG_(pp_UOperand)(u, 1, u->size, u->opcode==LOAD); 
@@ -1243,7 +1252,7 @@ Int VG_(get_reg_usage) ( UInstr* u, Tag tag, Int* regs, Bool* isWrites )
       case MMX2_RegRd: RD(2); break;
       case MMX2_RegWr: WR(2); break;
 
-      case SSE4: case SSE3:
+      case SSE4: case SSE3: case SSE5:
       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;
@@ -1399,7 +1408,7 @@ Int maybe_uinstrReadsArchReg ( UInstr* u )
       case SSE3a_MemWr: case SSE3a_MemRd:
       case SSE3g_RegRd: case SSE3g_RegWr: 
       case SSE3g1_RegWr: case SSE3g1_RegRd:
-      case SSE4: case SSE3:
+      case SSE4: case SSE3: case SSE5:
       case WIDEN:
       /* GETSEG and USESEG are to do with ArchRegS, not ArchReg */
       case GETSEG: case PUTSEG: 
@@ -2289,7 +2298,7 @@ void VG_(translate) ( /*IN*/  ThreadState* tst,
    UChar*      final_code;
    UCodeBlock* cb;
    Bool        notrace_until_done;
-   UInt        notrace_until_limit = 1900;
+   UInt        notrace_until_limit = 18000;
 
    VGP_PUSHCC(VgpTranslate);
    debugging_translation