]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Implement a bunch more MMX insns.
authorJulian Seward <jseward@acm.org>
Sun, 21 Nov 2004 12:30:18 +0000 (12:30 +0000)
committerJulian Seward <jseward@acm.org>
Sun, 21 Nov 2004 12:30:18 +0000 (12:30 +0000)
git-svn-id: svn://svn.valgrind.org/vex/trunk@570

VEX/priv/guest-x86/gdefs.h
VEX/priv/guest-x86/ghelpers.c
VEX/priv/guest-x86/toIR.c

index 4dd73b3bdf341e2c943edca2147df32e5298c2b7..b859915b336c9a768ac7201460f5c16d22e05ffb 100644 (file)
@@ -91,37 +91,48 @@ extern ULong calculate_RCR  ( UInt arg, UInt rot_amt, UInt eflags_in, UInt sz );
 
 /* --- Clean helpers for MMX --- */
 
-extern ULong calculate_vadd32x2 ( ULong, ULong );
-extern ULong calculate_vadd16x4 ( ULong, ULong );
-extern ULong calculate_vadd8x8  ( ULong, ULong );
+extern ULong calculate_add32x2 ( ULong, ULong );
+extern ULong calculate_add16x4 ( ULong, ULong );
+extern ULong calculate_add8x8  ( ULong, ULong );
 
-extern ULong calculate_vqadd16Sx4 ( ULong, ULong );
-extern ULong calculate_vqadd8Sx8  ( ULong, ULong );
+extern ULong calculate_qadd16Sx4 ( ULong, ULong );
+extern ULong calculate_qadd8Sx8  ( ULong, ULong );
 
-extern ULong calculate_vqadd16Ux4 ( ULong, ULong );
-extern ULong calculate_vqadd8Ux8  ( ULong, ULong );
+extern ULong calculate_qadd16Ux4 ( ULong, ULong );
+extern ULong calculate_qadd8Ux8  ( ULong, ULong );
 
-extern ULong calculate_vsub32x2 ( ULong, ULong );
-extern ULong calculate_vsub16x4 ( ULong, ULong );
-extern ULong calculate_vsub8x8  ( ULong, ULong );
+extern ULong calculate_sub32x2 ( ULong, ULong );
+extern ULong calculate_sub16x4 ( ULong, ULong );
+extern ULong calculate_sub8x8  ( ULong, ULong );
 
-extern ULong calculate_vqsub16Sx4 ( ULong, ULong );
-extern ULong calculate_vqsub8Sx8  ( ULong, ULong );
+extern ULong calculate_qsub16Sx4 ( ULong, ULong );
+extern ULong calculate_qsub8Sx8  ( ULong, ULong );
 
-extern ULong calculate_vqsub16Ux4 ( ULong, ULong );
-extern ULong calculate_vqsub8Ux8  ( ULong, ULong );
+extern ULong calculate_qsub16Ux4 ( ULong, ULong );
+extern ULong calculate_qsub8Ux8  ( ULong, ULong );
 
-extern ULong calculate_vmulhi16x4 ( ULong, ULong );
-extern ULong calculate_vmullo16x4 ( ULong, ULong );
+extern ULong calculate_mulhi16x4 ( ULong, ULong );
+extern ULong calculate_mullo16x4 ( ULong, ULong );
 
 extern ULong calculate_pmaddwd ( ULong, ULong );
 
-extern ULong calculate_vcmpeq32x2  ( ULong, ULong );
-extern ULong calculate_vcmpeq16x4  ( ULong, ULong );
-extern ULong calculate_vcmpeq8x8   ( ULong, ULong );
-extern ULong calculate_vcmpge32Sx2 ( ULong, ULong );
-extern ULong calculate_vcmpge16Sx4 ( ULong, ULong );
-extern ULong calculate_vcmpge8Sx8  ( ULong, ULong );
+extern ULong calculate_cmpeq32x2  ( ULong, ULong );
+extern ULong calculate_cmpeq16x4  ( ULong, ULong );
+extern ULong calculate_cmpeq8x8   ( ULong, ULong );
+extern ULong calculate_cmpge32Sx2 ( ULong, ULong );
+extern ULong calculate_cmpge16Sx4 ( ULong, ULong );
+extern ULong calculate_cmpge8Sx8  ( ULong, ULong );
+
+extern ULong calculate_packssdw ( ULong, ULong );
+extern ULong calculate_packsswb ( ULong, ULong );
+extern ULong calculate_packuswb ( ULong, ULong );
+
+extern ULong calculate_punpckhbw ( ULong, ULong );
+extern ULong calculate_punpcklbw ( ULong, ULong );
+extern ULong calculate_punpckhwd ( ULong, ULong );
+extern ULong calculate_punpcklwd ( ULong, ULong );
+extern ULong calculate_punpckhdq ( ULong, ULong );
+extern ULong calculate_punpckldq ( ULong, ULong );
 
 
 /* --- DIRTY HELPERS --- */
index 7d9f817d5c5c3bf4a0a2515aa35020cc967ef6f0..b0f4c16d696a2c1b14430a5499de623b7b5f1bfa 100644 (file)
@@ -1643,7 +1643,7 @@ static inline UShort sel16x4_2 ( ULong w64 )
 static inline UShort sel16x4_1 ( ULong w64 ) 
 {
    UInt lo32 = (UInt)w64;
-   return 0xFFFF & (UInt)(lo32 >> 16);
+   return 0xFFFF & (UShort)(lo32 >> 16);
 }
 static inline UShort sel16x4_0 ( ULong w64 ) 
 {
@@ -1815,13 +1815,31 @@ static inline UChar cmpge8S ( SChar xx, SChar yy )
    return xx>yy ? 0xFF : 0;
 }
 
+static inline Short qnarrow32Sto16 ( Int xx )
+{
+   if (xx < -32768) xx = -32768;
+   if (xx > 32767)  xx = 32767;
+   return (Short)xx;
+}
 
+static inline SChar qnarrow16Sto8 ( Int xx )
+{
+   if (xx < -128) xx = -128;
+   if (xx > 127)  xx = 127;
+   return (SChar)xx;
+}
+
+static inline UChar qnarrow16Uto8 ( Int xx )
+{
+   if (xx < 0)   xx = 0;
+   if (xx > 255) xx = 255;
+   return (UChar)xx;
+}
 
-/* Actually do something interesting! */
 
-/* Normal adds. */
+/* ------------ Normal addition ------------ */
 
-ULong calculate_vadd32x2 ( ULong xx, ULong yy )
+ULong calculate_add32x2 ( ULong xx, ULong yy )
 {
    return mk32x2(
              sel32x2_1(xx) + sel32x2_1(yy),
@@ -1829,7 +1847,7 @@ ULong calculate_vadd32x2 ( ULong xx, ULong yy )
           );
 }
 
-ULong calculate_vadd16x4 ( ULong xx, ULong yy )
+ULong calculate_add16x4 ( ULong xx, ULong yy )
 {
    return mk16x4(
              sel16x4_3(xx) + sel16x4_3(yy),
@@ -1839,7 +1857,7 @@ ULong calculate_vadd16x4 ( ULong xx, ULong yy )
           );
 }
 
-ULong calculate_vadd8x8 ( ULong xx, ULong yy )
+ULong calculate_add8x8 ( ULong xx, ULong yy )
 {
    return mk8x8(
              sel8x8_7(xx) + sel8x8_7(yy),
@@ -1853,9 +1871,9 @@ ULong calculate_vadd8x8 ( ULong xx, ULong yy )
           );
 }
 
-/* Saturated adds. */
+/* ------------ Saturating addition ------------ */
 
-ULong calculate_vqadd16Sx4 ( ULong xx, ULong yy )
+ULong calculate_qadd16Sx4 ( ULong xx, ULong yy )
 {
    return mk16x4(
              qadd16S( sel16x4_3(xx), sel16x4_3(yy) ),
@@ -1865,7 +1883,7 @@ ULong calculate_vqadd16Sx4 ( ULong xx, ULong yy )
           );
 }
 
-ULong calculate_vqadd8Sx8 ( ULong xx, ULong yy )
+ULong calculate_qadd8Sx8 ( ULong xx, ULong yy )
 {
    return mk8x8(
              qadd8S( sel8x8_7(xx), sel8x8_7(yy) ),
@@ -1879,7 +1897,7 @@ ULong calculate_vqadd8Sx8 ( ULong xx, ULong yy )
           );
 }
 
-ULong calculate_vqadd16Ux4 ( ULong xx, ULong yy )
+ULong calculate_qadd16Ux4 ( ULong xx, ULong yy )
 {
    return mk16x4(
              qadd16U( sel16x4_3(xx), sel16x4_3(yy) ),
@@ -1889,7 +1907,7 @@ ULong calculate_vqadd16Ux4 ( ULong xx, ULong yy )
           );
 }
 
-ULong calculate_vqadd8Ux8 ( ULong xx, ULong yy )
+ULong calculate_qadd8Ux8 ( ULong xx, ULong yy )
 {
    return mk8x8(
              qadd8U( sel8x8_7(xx), sel8x8_7(yy) ),
@@ -1903,9 +1921,9 @@ ULong calculate_vqadd8Ux8 ( ULong xx, ULong yy )
           );
 }
 
-/* Normal subtracts. */
+/* ------------ Normal subtraction ------------ */
 
-ULong calculate_vsub32x2 ( ULong xx, ULong yy )
+ULong calculate_sub32x2 ( ULong xx, ULong yy )
 {
    return mk32x2(
              sel32x2_1(xx) - sel32x2_1(yy),
@@ -1913,7 +1931,7 @@ ULong calculate_vsub32x2 ( ULong xx, ULong yy )
           );
 }
 
-ULong calculate_vsub16x4 ( ULong xx, ULong yy )
+ULong calculate_sub16x4 ( ULong xx, ULong yy )
 {
    return mk16x4(
              sel16x4_3(xx) - sel16x4_3(yy),
@@ -1923,7 +1941,7 @@ ULong calculate_vsub16x4 ( ULong xx, ULong yy )
           );
 }
 
-ULong calculate_vsub8x8 ( ULong xx, ULong yy )
+ULong calculate_sub8x8 ( ULong xx, ULong yy )
 {
    return mk8x8(
              sel8x8_7(xx) - sel8x8_7(yy),
@@ -1937,9 +1955,9 @@ ULong calculate_vsub8x8 ( ULong xx, ULong yy )
           );
 }
 
-/* Saturated subtracts. */
+/* ------------ Saturating subtraction ------------ */
 
-ULong calculate_vqsub16Sx4 ( ULong xx, ULong yy )
+ULong calculate_qsub16Sx4 ( ULong xx, ULong yy )
 {
    return mk16x4(
              qsub16S( sel16x4_3(xx), sel16x4_3(yy) ),
@@ -1949,7 +1967,7 @@ ULong calculate_vqsub16Sx4 ( ULong xx, ULong yy )
           );
 }
 
-ULong calculate_vqsub8Sx8 ( ULong xx, ULong yy )
+ULong calculate_qsub8Sx8 ( ULong xx, ULong yy )
 {
    return mk8x8(
              qsub8S( sel8x8_7(xx), sel8x8_7(yy) ),
@@ -1963,7 +1981,7 @@ ULong calculate_vqsub8Sx8 ( ULong xx, ULong yy )
           );
 }
 
-ULong calculate_vqsub16Ux4 ( ULong xx, ULong yy )
+ULong calculate_qsub16Ux4 ( ULong xx, ULong yy )
 {
    return mk16x4(
              qsub16U( sel16x4_3(xx), sel16x4_3(yy) ),
@@ -1973,7 +1991,7 @@ ULong calculate_vqsub16Ux4 ( ULong xx, ULong yy )
           );
 }
 
-ULong calculate_vqsub8Ux8 ( ULong xx, ULong yy )
+ULong calculate_qsub8Ux8 ( ULong xx, ULong yy )
 {
    return mk8x8(
              qsub8U( sel8x8_7(xx), sel8x8_7(yy) ),
@@ -1987,9 +2005,9 @@ ULong calculate_vqsub8Ux8 ( ULong xx, ULong yy )
           );
 }
 
-/* Multiplication. */
+/* ------------ Multiplication ------------ */
 
-ULong calculate_vmulhi16x4 ( ULong xx, ULong yy )
+ULong calculate_mulhi16x4 ( ULong xx, ULong yy )
 {
    return mk16x4(
              mulhi16S( sel16x4_3(xx), sel16x4_3(yy) ),
@@ -1999,7 +2017,7 @@ ULong calculate_vmulhi16x4 ( ULong xx, ULong yy )
           );
 }
 
-ULong calculate_vmullo16x4 ( ULong xx, ULong yy )
+ULong calculate_mullo16x4 ( ULong xx, ULong yy )
 {
    return mk16x4(
              mullo16S( sel16x4_3(xx), sel16x4_3(yy) ),
@@ -2020,9 +2038,9 @@ ULong calculate_pmaddwd ( ULong xx, ULong yy )
       );
 }
 
-/* Comparison. */
+/* ------------ Comparison ------------ */
 
-ULong calculate_vcmpeq32x2 ( ULong xx, ULong yy )
+ULong calculate_cmpeq32x2 ( ULong xx, ULong yy )
 {
    return mk32x2(
              cmpeq32( sel32x2_1(xx), sel32x2_1(yy) ),
@@ -2030,7 +2048,7 @@ ULong calculate_vcmpeq32x2 ( ULong xx, ULong yy )
           );
 }
 
-ULong calculate_vcmpeq16x4 ( ULong xx, ULong yy )
+ULong calculate_cmpeq16x4 ( ULong xx, ULong yy )
 {
    return mk16x4(
              cmpeq16( sel16x4_3(xx), sel16x4_3(yy) ),
@@ -2040,7 +2058,7 @@ ULong calculate_vcmpeq16x4 ( ULong xx, ULong yy )
           );
 }
 
-ULong calculate_vcmpeq8x8 ( ULong xx, ULong yy )
+ULong calculate_cmpeq8x8 ( ULong xx, ULong yy )
 {
    return mk8x8(
              cmpeq8( sel8x8_7(xx), sel8x8_7(yy) ),
@@ -2054,7 +2072,7 @@ ULong calculate_vcmpeq8x8 ( ULong xx, ULong yy )
           );
 }
 
-ULong calculate_vcmpge32Sx2 ( ULong xx, ULong yy )
+ULong calculate_cmpge32Sx2 ( ULong xx, ULong yy )
 {
    return mk32x2(
              cmpge32S( sel32x2_1(xx), sel32x2_1(yy) ),
@@ -2062,7 +2080,7 @@ ULong calculate_vcmpge32Sx2 ( ULong xx, ULong yy )
           );
 }
 
-ULong calculate_vcmpge16Sx4 ( ULong xx, ULong yy )
+ULong calculate_cmpge16Sx4 ( ULong xx, ULong yy )
 {
    return mk16x4(
              cmpge16S( sel16x4_3(xx), sel16x4_3(yy) ),
@@ -2072,7 +2090,7 @@ ULong calculate_vcmpge16Sx4 ( ULong xx, ULong yy )
           );
 }
 
-ULong calculate_vcmpge8Sx8 ( ULong xx, ULong yy )
+ULong calculate_cmpge8Sx8 ( ULong xx, ULong yy )
 {
    return mk8x8(
              cmpge8S( sel8x8_7(xx), sel8x8_7(yy) ),
@@ -2086,6 +2104,129 @@ ULong calculate_vcmpge8Sx8 ( ULong xx, ULong yy )
           );
 }
 
+/* ------------ Pack / unpack ------------ */
+
+ULong calculate_packssdw ( ULong dst, ULong src )
+{
+   Int d = sel32x2_1(dst);
+   Int c = sel32x2_0(dst);
+   Int b = sel32x2_1(src);
+   Int a = sel32x2_0(src);
+   return mk16x4( 
+             qnarrow32Sto16(d),
+             qnarrow32Sto16(c),
+             qnarrow32Sto16(b),
+             qnarrow32Sto16(a)
+          );
+}
+
+ULong calculate_packsswb ( ULong dst, ULong src )
+{
+   Int h = sel16x4_3(dst);
+   Int g = sel16x4_2(dst);
+   Int f = sel16x4_1(dst);
+   Int e = sel16x4_0(dst);
+   Int d = sel16x4_3(src);
+   Int c = sel16x4_2(src);
+   Int b = sel16x4_1(src);
+   Int a = sel16x4_0(src);
+   return mk8x8( 
+             qnarrow16Sto8(h),
+             qnarrow16Sto8(g),
+             qnarrow16Sto8(f),
+             qnarrow16Sto8(e),
+             qnarrow16Sto8(d),
+             qnarrow16Sto8(c),
+             qnarrow16Sto8(b),
+             qnarrow16Sto8(a)
+          );
+}
+
+ULong calculate_packuswb ( ULong dst, ULong src )
+{
+   Int h = sel16x4_3(dst);
+   Int g = sel16x4_2(dst);
+   Int f = sel16x4_1(dst);
+   Int e = sel16x4_0(dst);
+   Int d = sel16x4_3(src);
+   Int c = sel16x4_2(src);
+   Int b = sel16x4_1(src);
+   Int a = sel16x4_0(src);
+   return mk8x8( 
+             qnarrow16Uto8(h),
+             qnarrow16Uto8(g),
+             qnarrow16Uto8(f),
+             qnarrow16Uto8(e),
+             qnarrow16Uto8(d),
+             qnarrow16Uto8(c),
+             qnarrow16Uto8(b),
+             qnarrow16Uto8(a)
+          );
+}
+
+ULong calculate_punpckhbw ( ULong dst, ULong src )
+{
+  return mk8x8(
+            sel8x8_7(src),
+            sel8x8_7(dst),
+            sel8x8_6(src),
+            sel8x8_6(dst),
+            sel8x8_5(src),
+            sel8x8_5(dst),
+            sel8x8_4(src),
+            sel8x8_4(dst)
+         );
+}
+
+ULong calculate_punpcklbw ( ULong dst, ULong src )
+{
+  return mk8x8(
+            sel8x8_3(src),
+            sel8x8_3(dst),
+            sel8x8_2(src),
+            sel8x8_2(dst),
+            sel8x8_1(src),
+            sel8x8_1(dst),
+            sel8x8_0(src),
+            sel8x8_0(dst)
+         );
+}
+
+ULong calculate_punpckhwd ( ULong dst, ULong src )
+{
+  return mk16x4(
+            sel16x4_3(src),
+            sel16x4_3(dst),
+            sel16x4_2(src),
+            sel16x4_2(dst)
+         );
+}
+
+ULong calculate_punpcklwd ( ULong dst, ULong src )
+{
+  return mk16x4(
+            sel16x4_1(src),
+            sel16x4_1(dst),
+            sel16x4_0(src),
+            sel16x4_0(dst)
+         );
+}
+
+ULong calculate_punpckhdq ( ULong dst, ULong src )
+{
+  return mk32x2(
+            sel32x2_1(src),
+            sel32x2_1(dst)
+         );
+}
+
+ULong calculate_punpckldq ( ULong dst, ULong src )
+{
+  return mk32x2(
+            sel32x2_0(src),
+            sel32x2_0(dst)
+         );
+}
 
 
 /*-----------------------------------------------------------*/
index bb320601440cdf77d36fa7d1989418bbcd31c566..6bed7930546aafee5b4501f08e9cc8d91565f7d1 100644 (file)
@@ -4636,46 +4636,66 @@ UInt dis_MMXop_regmem_to_reg ( UChar sorb,
                                Char* name,
                                Bool  show_granularity )
 {
-   Char  dis_buf[50];
-   UChar modrm = getIByte(delta);
-   Bool  isReg = epartIsReg(modrm);
+   Char    dis_buf[50];
+   UChar   modrm = getIByte(delta);
+   Bool    isReg = epartIsReg(modrm);
+   IRExpr* argL  = NULL;
+   IRExpr* argR  = NULL;
+   IRTemp  res   = newTemp(Ity_I64);
 
 #  define XXX(_name) hAddr = &_name; hName = #_name;
 
    void* hAddr = NULL;
    Char* hName = NULL;
    switch (opc) {
-      case 0xFC: XXX(calculate_vadd8x8); break;
-      case 0xFD: XXX(calculate_vadd16x4); break;
-      case 0xFE: XXX(calculate_vadd32x2); break;
+      case 0xFC: XXX(calculate_add8x8); break;
+      case 0xFD: XXX(calculate_add16x4); break;
+      case 0xFE: XXX(calculate_add32x2); break;
 
-      case 0xEC: XXX(calculate_vqadd8Sx8); break;
-      case 0xED: XXX(calculate_vqadd16Sx4); break;
+      case 0xEC: XXX(calculate_qadd8Sx8); break;
+      case 0xED: XXX(calculate_qadd16Sx4); break;
 
-      case 0xDC: XXX(calculate_vqadd8Ux8); break;
-      case 0xDD: XXX(calculate_vqadd16Ux4); break;
+      case 0xDC: XXX(calculate_qadd8Ux8); break;
+      case 0xDD: XXX(calculate_qadd16Ux4); break;
 
-      case 0xF8: XXX(calculate_vsub8x8);  break;
-      case 0xF9: XXX(calculate_vsub16x4); break;
-      case 0xFA: XXX(calculate_vsub32x2); break;
+      case 0xF8: XXX(calculate_sub8x8);  break;
+      case 0xF9: XXX(calculate_sub16x4); break;
+      case 0xFA: XXX(calculate_sub32x2); break;
 
-      case 0xE8: XXX(calculate_vqsub8Sx8); break;
-      case 0xE9: XXX(calculate_vqsub16Sx4); break;
+      case 0xE8: XXX(calculate_qsub8Sx8); break;
+      case 0xE9: XXX(calculate_qsub16Sx4); break;
 
-      case 0xD8: XXX(calculate_vqsub8Ux8); break;
-      case 0xD9: XXX(calculate_vqsub16Ux4); break;
+      case 0xD8: XXX(calculate_qsub8Ux8); break;
+      case 0xD9: XXX(calculate_qsub16Ux4); break;
 
-      case 0xE5: XXX(calculate_vmulhi16x4); break;
-      case 0xD5: XXX(calculate_vmullo16x4); break;
+      case 0xE5: XXX(calculate_mulhi16x4); break;
+      case 0xD5: XXX(calculate_mullo16x4); break;
       case 0xF5: XXX(calculate_pmaddwd); break;
 
-      case 0x74: XXX(calculate_vcmpeq8x8); break;
-      case 0x75: XXX(calculate_vcmpeq16x4); break;
-      case 0x76: XXX(calculate_vcmpeq32x2); break;
+      case 0x74: XXX(calculate_cmpeq8x8); break;
+      case 0x75: XXX(calculate_cmpeq16x4); break;
+      case 0x76: XXX(calculate_cmpeq32x2); break;
 
-      case 0x64: XXX(calculate_vcmpge8Sx8); break;
-      case 0x65: XXX(calculate_vcmpge16Sx4); break;
-      case 0x66: XXX(calculate_vcmpge32Sx2); break;
+      case 0x64: XXX(calculate_cmpge8Sx8); break;
+      case 0x65: XXX(calculate_cmpge16Sx4); break;
+      case 0x66: XXX(calculate_cmpge32Sx2); break;
+
+      case 0x6B: XXX(calculate_packssdw); break;
+      case 0x63: XXX(calculate_packsswb); break;
+      case 0x67: XXX(calculate_packuswb); break;
+
+      case 0x68: XXX(calculate_punpckhbw); break;
+      case 0x69: XXX(calculate_punpckhwd); break;
+      case 0x6A: XXX(calculate_punpckhdq); break;
+
+      case 0x60: XXX(calculate_punpcklbw); break;
+      case 0x61: XXX(calculate_punpcklwd); break;
+      case 0x62: XXX(calculate_punpckldq); break;
+
+      case 0xDB: break; /* AND */
+      case 0xDF: break; /* ANDN */
+      case 0xEB: break; /* OR */
+      case 0xEF: break; /* XOR */
 
       default: 
          vex_printf("\n0x%x\n", (Int)opc);
@@ -4684,33 +4704,48 @@ UInt dis_MMXop_regmem_to_reg ( UChar sorb,
 
 #  undef XXX
 
+   argL = getMMXReg(gregOfRM(modrm));
+
    if (isReg) {
-vassert(0);
+      vassert(0);
       delta++;
-      putMMXReg( 
-         gregOfRM(modrm),
-         mkIRExprCCall(
-            Ity_I64, 
-            0/*regparms*/, hName, hAddr,
-            mkIRExprVec_2( getMMXReg(gregOfRM(modrm)),
-                           getMMXReg(eregOfRM(modrm)) )
-         ) 
-      );
+      argR = getMMXReg(eregOfRM(modrm));
    } else {
       Int    len;
       IRTemp addr = disAMode( &len, sorb, delta, dis_buf );
       delta += len;
-      putMMXReg( 
-         gregOfRM(modrm),
-         mkIRExprCCall(
-            Ity_I64, 
-            0/*regparms*/, hName, hAddr,
-            mkIRExprVec_2( getMMXReg(gregOfRM(modrm)),
-                           loadLE(Ity_I64, mkexpr(addr)) )
-         ) 
-      );
+      argR = loadLE(Ity_I64, mkexpr(addr));
+   }
+
+   switch (opc) {
+      case 0xDB: 
+         assign(res, binop(Iop_And64, argL, argR) ); 
+         break;
+      case 0xDF: 
+         assign(res, binop(Iop_And64, argL, unop(Iop_Not64, argR)) ); 
+         break;
+      case 0xEB: 
+         assign(res, binop(Iop_Or64, argL, argR) ); 
+         break;
+      case 0xEF: 
+         /* Possibly do better here if argL and argR are the same reg */
+         assign(res, binop(Iop_Xor64, argL, argR) ); 
+         break;
+      default:
+         vassert(hAddr);
+         vassert(hName);
+         assign( res, 
+                 mkIRExprCCall(
+                    Ity_I64, 
+                    0/*regparms*/, hName, hAddr,
+                    mkIRExprVec_2( argL, argR )
+                 ) 
+               );
+         break;
    }
 
+   putMMXReg( gregOfRM(modrm), mkexpr(res) );
+
    DIP("%s%s %s, %s\n", 
        name, show_granularity ? nameMMXGran(opc & 3) : (Char*)"",
        ( isReg ? nameMMXReg(eregOfRM(modrm)) : dis_buf ),
@@ -4760,7 +4795,7 @@ UInt dis_MMX ( Bool* decode_ok, UChar sorb, Int sz, UInt delta )
          vassert(sz == 4);
          modrm = getIByte(delta);
          if (epartIsReg(modrm)) {
-vassert(0);
+         vassert(0);
 #if 0
             eip++;
             uInstr1(cb, MMX2, 0, 
@@ -4845,6 +4880,55 @@ vassert(0);
          delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pcmpgt", True );
          break;
 
+      case 0x6B: /* PACKSSDW (src)mmxreg-or-mem, (dst)mmxreg */
+         vassert(sz == 4);
+         delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "packssdw", False );
+         break;
+
+      case 0x63: /* PACKSSWB (src)mmxreg-or-mem, (dst)mmxreg */
+         vassert(sz == 4);
+         delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "packsswb", False );
+         break;
+
+      case 0x67: /* PACKUSWB (src)mmxreg-or-mem, (dst)mmxreg */
+         vassert(sz == 4);
+         delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "packuswb", False );
+         break;
+
+      case 0x68: 
+      case 0x69: 
+      case 0x6A: /* PUNPCKHgg (src)mmxreg-or-mem, (dst)mmxreg */
+         vassert(sz == 4);
+         delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "punpckh", True );
+         break;
+
+      case 0x60: 
+      case 0x61: 
+      case 0x62: /* PUNPCKLgg (src)mmxreg-or-mem, (dst)mmxreg */
+         vassert(sz == 4);
+         delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "punpckl", True );
+         break;
+
+      case 0xDB: /* PAND (src)mmxreg-or-mem, (dst)mmxreg */
+         vassert(sz == 4);
+         delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pand", False );
+         break;
+
+      case 0xDF: /* PANDN (src)mmxreg-or-mem, (dst)mmxreg */
+         vassert(sz == 4);
+         delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pandn", False );
+         break;
+
+      case 0xEB: /* POR (src)mmxreg-or-mem, (dst)mmxreg */
+         vassert(sz == 4);
+         delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "por", False );
+         break;
+
+      case 0xEF: /* PXOR (src)mmxreg-or-mem, (dst)mmxreg */
+         vassert(sz == 4);
+         delta = dis_MMXop_regmem_to_reg ( sorb, delta, opc, "pxor", False );
+         break;
+
       default:
          *decode_ok = False;
          return delta; /* ignored */
@@ -9488,6 +9572,23 @@ static DisResult disInstr ( /*IN*/  Bool    resteerOK,
       case 0x65: 
       case 0x66: /* PCMPGTgg (src)mmxreg-or-mem, (dst)mmxreg */
 
+      case 0x6B: /* PACKSSDW (src)mmxreg-or-mem, (dst)mmxreg */
+      case 0x63: /* PACKSSWB (src)mmxreg-or-mem, (dst)mmxreg */
+      case 0x67: /* PACKUSWB (src)mmxreg-or-mem, (dst)mmxreg */
+
+      case 0x68: 
+      case 0x69: 
+      case 0x6A: /* PUNPCKHgg (src)mmxreg-or-mem, (dst)mmxreg */
+
+      case 0x60: 
+      case 0x61: 
+      case 0x62: /* PUNPCKLgg (src)mmxreg-or-mem, (dst)mmxreg */
+
+      case 0xDB: /* PAND (src)mmxreg-or-mem, (dst)mmxreg */
+      case 0xDF: /* PANDN (src)mmxreg-or-mem, (dst)mmxreg */
+      case 0xEB: /* POR (src)mmxreg-or-mem, (dst)mmxreg */
+      case 0xEF: /* PXOR (src)mmxreg-or-mem, (dst)mmxreg */
+
       case 0x6F: /* MOVQ (src)mmxreg-or-mem, (dst)mmxreg */
       {
          UInt delta0    = delta-1;