#include <math.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>

typedef union {
  char sb[1];
  unsigned char ub[1];
} reg8_t;

typedef union {
  char sb[2];
  unsigned char ub[2];
  short sw[1];
  unsigned short uw[1];
} reg16_t;

typedef union {
  char sb[4];
  unsigned char ub[4];
  short sw[2];
  unsigned short uw[2];
  long int sd[1];
  unsigned long int ud[1];
  float ps[1];
} reg32_t;

typedef union {
  char sb[8];
  unsigned char ub[8];
  short sw[4];
  unsigned short uw[4];
  long int sd[2];
  unsigned long int ud[2];
  long long int sq[1];
  unsigned long long int uq[1];
  float ps[2];
  double pd[1];
} reg64_t __attribute__ ((aligned (8)));

typedef union {
  char sb[16];
  unsigned char ub[16];
  short sw[8];
  unsigned short uw[8];
  long int sd[4];
  unsigned long int ud[4];
  long long int sq[2];
  unsigned long long int uq[2];
  float ps[4];
  double pd[2];
} reg128_t __attribute__ ((aligned (16)));

static sigjmp_buf catchpoint;

static void handle_sigill(int signum)
{
   siglongjmp(catchpoint, 1);
}

__attribute__((unused))
static int eq_float(float f1, float f2)
{
   return f1 == f2 || fabsf(f1 - f2) < fabsf(f1) * 1.5 * pow(2,-12);
}

__attribute__((unused))
static int eq_double(double d1, double d2)
{
   return d1 == d2 || fabs(d1 - d2) < fabs(d1) * 1.5 * pow(2,-12);
}

static void movntq_1(void)
{
   reg64_t arg0 = { .uq = { 0x0123456789abcdefULL } };
   reg64_t arg1 = { .uq = { 0x1212121234343434ULL } };
   reg64_t result0 = arg1;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %1, %%mm6\n"
         "movntq %%mm6, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg0), "m" (arg1), "m" (state[0])
         : "mm6", "mm7"
      );

      if (result0.uq[0] == 0x0123456789abcdefULL )
      {
         printf("movntq_1 ... ok\n");
      }
      else
      {
         printf("movntq_1 ... not ok\n");
         printf("  result0.uq[0] = %llu (expected %llu)\n", result0.uq[0], 0x0123456789abcdefULL);
      }
   }
   else
   {
      printf("movntq_1 ... failed\n");
   }

   return;
}

static void pavgb_1(void)
{
   reg64_t arg0 = { .ub = { 11U, 22U, 33U, 44U, 55U, 66U, 77U, 88U } };
   reg64_t arg1 = { .ub = { 15U, 25U, 35U, 45U, 55U, 65U, 75U, 85U } };
   reg64_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %1, %%mm6\n"
         "movq %2, %%mm7\n"
         "pavgb %%mm6, %%mm7\n"
         "movq %%mm7, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg0), "m" (arg1), "m" (state[0])
         : "mm6", "mm7"
      );

      if (result0.ub[0] == 13U && result0.ub[1] == 24U && result0.ub[2] == 34U && result0.ub[3] == 45U && result0.ub[4] == 55U && result0.ub[5] == 66U && result0.ub[6] == 76U && result0.ub[7] == 87U )
      {
         printf("pavgb_1 ... ok\n");
      }
      else
      {
         printf("pavgb_1 ... not ok\n");
         printf("  result0.ub[0] = %u (expected %u)\n", result0.ub[0], 13U);
         printf("  result0.ub[1] = %u (expected %u)\n", result0.ub[1], 24U);
         printf("  result0.ub[2] = %u (expected %u)\n", result0.ub[2], 34U);
         printf("  result0.ub[3] = %u (expected %u)\n", result0.ub[3], 45U);
         printf("  result0.ub[4] = %u (expected %u)\n", result0.ub[4], 55U);
         printf("  result0.ub[5] = %u (expected %u)\n", result0.ub[5], 66U);
         printf("  result0.ub[6] = %u (expected %u)\n", result0.ub[6], 76U);
         printf("  result0.ub[7] = %u (expected %u)\n", result0.ub[7], 87U);
      }
   }
   else
   {
      printf("pavgb_1 ... failed\n");
   }

   return;
}

static void pavgb_2(void)
{
   reg64_t arg0 = { .ub = { 11U, 22U, 33U, 44U, 55U, 66U, 77U, 88U } };
   reg64_t arg1 = { .ub = { 15U, 25U, 35U, 45U, 55U, 65U, 75U, 85U } };
   reg64_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %2, %%mm7\n"
         "pavgb %1, %%mm7\n"
         "movq %%mm7, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg0), "m" (arg1), "m" (state[0])
         : "mm6", "mm7"
      );

      if (result0.ub[0] == 13U && result0.ub[1] == 24U && result0.ub[2] == 34U && result0.ub[3] == 45U && result0.ub[4] == 55U && result0.ub[5] == 66U && result0.ub[6] == 76U && result0.ub[7] == 87U )
      {
         printf("pavgb_2 ... ok\n");
      }
      else
      {
         printf("pavgb_2 ... not ok\n");
         printf("  result0.ub[0] = %u (expected %u)\n", result0.ub[0], 13U);
         printf("  result0.ub[1] = %u (expected %u)\n", result0.ub[1], 24U);
         printf("  result0.ub[2] = %u (expected %u)\n", result0.ub[2], 34U);
         printf("  result0.ub[3] = %u (expected %u)\n", result0.ub[3], 45U);
         printf("  result0.ub[4] = %u (expected %u)\n", result0.ub[4], 55U);
         printf("  result0.ub[5] = %u (expected %u)\n", result0.ub[5], 66U);
         printf("  result0.ub[6] = %u (expected %u)\n", result0.ub[6], 76U);
         printf("  result0.ub[7] = %u (expected %u)\n", result0.ub[7], 87U);
      }
   }
   else
   {
      printf("pavgb_2 ... failed\n");
   }

   return;
}

static void pavgw_1(void)
{
   reg64_t arg0 = { .uw = { 1122, 3344, 5566, 7788 } };
   reg64_t arg1 = { .uw = { 1525, 3545, 5565, 7585 } };
   reg64_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %1, %%mm6\n"
         "movq %2, %%mm7\n"
         "pavgw %%mm6, %%mm7\n"
         "movq %%mm7, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg0), "m" (arg1), "m" (state[0])
         : "mm6", "mm7"
      );

      if (result0.uw[0] == 1324 && result0.uw[1] == 3445 && result0.uw[2] == 5566 && result0.uw[3] == 7687 )
      {
         printf("pavgw_1 ... ok\n");
      }
      else
      {
         printf("pavgw_1 ... not ok\n");
         printf("  result0.uw[0] = %u (expected %u)\n", result0.uw[0], 1324);
         printf("  result0.uw[1] = %u (expected %u)\n", result0.uw[1], 3445);
         printf("  result0.uw[2] = %u (expected %u)\n", result0.uw[2], 5566);
         printf("  result0.uw[3] = %u (expected %u)\n", result0.uw[3], 7687);
      }
   }
   else
   {
      printf("pavgw_1 ... failed\n");
   }

   return;
}

static void pavgw_2(void)
{
   reg64_t arg0 = { .uw = { 1122, 3344, 5566, 7788 } };
   reg64_t arg1 = { .uw = { 1525, 3545, 5565, 7585 } };
   reg64_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %2, %%mm7\n"
         "pavgw %1, %%mm7\n"
         "movq %%mm7, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg0), "m" (arg1), "m" (state[0])
         : "mm6", "mm7"
      );

      if (result0.uw[0] == 1324 && result0.uw[1] == 3445 && result0.uw[2] == 5566 && result0.uw[3] == 7687 )
      {
         printf("pavgw_2 ... ok\n");
      }
      else
      {
         printf("pavgw_2 ... not ok\n");
         printf("  result0.uw[0] = %u (expected %u)\n", result0.uw[0], 1324);
         printf("  result0.uw[1] = %u (expected %u)\n", result0.uw[1], 3445);
         printf("  result0.uw[2] = %u (expected %u)\n", result0.uw[2], 5566);
         printf("  result0.uw[3] = %u (expected %u)\n", result0.uw[3], 7687);
      }
   }
   else
   {
      printf("pavgw_2 ... failed\n");
   }

   return;
}

static void pextrw_1(void)
{
   reg64_t arg1 = { .uw = { 1234, 5678, 4321, 8765 } };
   reg32_t arg2 = { .ud = { 0xffffffffUL } };
   reg32_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %1, %%mm6\n"
         "movl %2, %%eax\n"
         "pextrw $0, %%mm6, %%eax\n"
         "movl %%eax, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg1), "m" (arg2), "m" (state[0])
         : "mm6", "eax"
      );

      if (result0.ud[0] == 1234UL )
      {
         printf("pextrw_1 ... ok\n");
      }
      else
      {
         printf("pextrw_1 ... not ok\n");
         printf("  result0.ud[0] = %lu (expected %lu)\n", result0.ud[0], 1234UL);
      }
   }
   else
   {
      printf("pextrw_1 ... failed\n");
   }

   return;
}

static void pextrw_2(void)
{
   reg64_t arg1 = { .uw = { 1234, 5678, 4321, 8765 } };
   reg32_t arg2 = { .ud = { 0xffffffffUL } };
   reg32_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %1, %%mm6\n"
         "movl %2, %%eax\n"
         "pextrw $1, %%mm6, %%eax\n"
         "movl %%eax, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg1), "m" (arg2), "m" (state[0])
         : "mm6", "eax"
      );

      if (result0.ud[0] == 5678UL )
      {
         printf("pextrw_2 ... ok\n");
      }
      else
      {
         printf("pextrw_2 ... not ok\n");
         printf("  result0.ud[0] = %lu (expected %lu)\n", result0.ud[0], 5678UL);
      }
   }
   else
   {
      printf("pextrw_2 ... failed\n");
   }

   return;
}

static void pextrw_3(void)
{
   reg64_t arg1 = { .uw = { 1234, 5678, 4321, 8765 } };
   reg32_t arg2 = { .ud = { 0xffffffffUL } };
   reg32_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %1, %%mm6\n"
         "movl %2, %%eax\n"
         "pextrw $2, %%mm6, %%eax\n"
         "movl %%eax, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg1), "m" (arg2), "m" (state[0])
         : "mm6", "eax"
      );

      if (result0.ud[0] == 4321UL )
      {
         printf("pextrw_3 ... ok\n");
      }
      else
      {
         printf("pextrw_3 ... not ok\n");
         printf("  result0.ud[0] = %lu (expected %lu)\n", result0.ud[0], 4321UL);
      }
   }
   else
   {
      printf("pextrw_3 ... failed\n");
   }

   return;
}

static void pextrw_4(void)
{
   reg64_t arg1 = { .uw = { 1234, 5678, 4321, 8765 } };
   reg32_t arg2 = { .ud = { 0xffffffffUL } };
   reg32_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %1, %%mm6\n"
         "movl %2, %%eax\n"
         "pextrw $3, %%mm6, %%eax\n"
         "movl %%eax, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg1), "m" (arg2), "m" (state[0])
         : "mm6", "eax"
      );

      if (result0.ud[0] == 8765UL )
      {
         printf("pextrw_4 ... ok\n");
      }
      else
      {
         printf("pextrw_4 ... not ok\n");
         printf("  result0.ud[0] = %lu (expected %lu)\n", result0.ud[0], 8765UL);
      }
   }
   else
   {
      printf("pextrw_4 ... failed\n");
   }

   return;
}

static void pinsrw_1(void)
{
   reg32_t arg1 = { .ud = { 0xffffffffUL } };
   reg64_t arg2 = { .uw = { 1234, 5678, 4321, 8765 } };
   reg64_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movl %1, %%eax\n"
         "movq %2, %%mm6\n"
         "pinsrw $0, %%eax, %%mm6\n"
         "movq %%mm6, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg1), "m" (arg2), "m" (state[0])
         : "eax", "mm6"
      );

      if (result0.uw[0] == 65535 && result0.uw[1] == 5678 && result0.uw[2] == 4321 && result0.uw[3] == 8765 )
      {
         printf("pinsrw_1 ... ok\n");
      }
      else
      {
         printf("pinsrw_1 ... not ok\n");
         printf("  result0.uw[0] = %u (expected %u)\n", result0.uw[0], 65535);
         printf("  result0.uw[1] = %u (expected %u)\n", result0.uw[1], 5678);
         printf("  result0.uw[2] = %u (expected %u)\n", result0.uw[2], 4321);
         printf("  result0.uw[3] = %u (expected %u)\n", result0.uw[3], 8765);
      }
   }
   else
   {
      printf("pinsrw_1 ... failed\n");
   }

   return;
}

static void pinsrw_2(void)
{
   reg32_t arg1 = { .ud = { 0xffffffffUL } };
   reg64_t arg2 = { .uw = { 1234, 5678, 4321, 8765 } };
   reg64_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movl %1, %%eax\n"
         "movq %2, %%mm6\n"
         "pinsrw $1, %%eax, %%mm6\n"
         "movq %%mm6, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg1), "m" (arg2), "m" (state[0])
         : "eax", "mm6"
      );

      if (result0.uw[0] == 1234 && result0.uw[1] == 65535 && result0.uw[2] == 4321 && result0.uw[3] == 8765 )
      {
         printf("pinsrw_2 ... ok\n");
      }
      else
      {
         printf("pinsrw_2 ... not ok\n");
         printf("  result0.uw[0] = %u (expected %u)\n", result0.uw[0], 1234);
         printf("  result0.uw[1] = %u (expected %u)\n", result0.uw[1], 65535);
         printf("  result0.uw[2] = %u (expected %u)\n", result0.uw[2], 4321);
         printf("  result0.uw[3] = %u (expected %u)\n", result0.uw[3], 8765);
      }
   }
   else
   {
      printf("pinsrw_2 ... failed\n");
   }

   return;
}

static void pinsrw_3(void)
{
   reg32_t arg1 = { .ud = { 0xffffffffUL } };
   reg64_t arg2 = { .uw = { 1234, 5678, 4321, 8765 } };
   reg64_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movl %1, %%eax\n"
         "movq %2, %%mm6\n"
         "pinsrw $2, %%eax, %%mm6\n"
         "movq %%mm6, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg1), "m" (arg2), "m" (state[0])
         : "eax", "mm6"
      );

      if (result0.uw[0] == 1234 && result0.uw[1] == 5678 && result0.uw[2] == 65535 && result0.uw[3] == 8765 )
      {
         printf("pinsrw_3 ... ok\n");
      }
      else
      {
         printf("pinsrw_3 ... not ok\n");
         printf("  result0.uw[0] = %u (expected %u)\n", result0.uw[0], 1234);
         printf("  result0.uw[1] = %u (expected %u)\n", result0.uw[1], 5678);
         printf("  result0.uw[2] = %u (expected %u)\n", result0.uw[2], 65535);
         printf("  result0.uw[3] = %u (expected %u)\n", result0.uw[3], 8765);
      }
   }
   else
   {
      printf("pinsrw_3 ... failed\n");
   }

   return;
}

static void pinsrw_4(void)
{
   reg32_t arg1 = { .ud = { 0xffffffffUL } };
   reg64_t arg2 = { .uw = { 1234, 5678, 4321, 8765 } };
   reg64_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movl %1, %%eax\n"
         "movq %2, %%mm6\n"
         "pinsrw $3, %%eax, %%mm6\n"
         "movq %%mm6, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg1), "m" (arg2), "m" (state[0])
         : "eax", "mm6"
      );

      if (result0.uw[0] == 1234 && result0.uw[1] == 5678 && result0.uw[2] == 4321 && result0.uw[3] == 65535 )
      {
         printf("pinsrw_4 ... ok\n");
      }
      else
      {
         printf("pinsrw_4 ... not ok\n");
         printf("  result0.uw[0] = %u (expected %u)\n", result0.uw[0], 1234);
         printf("  result0.uw[1] = %u (expected %u)\n", result0.uw[1], 5678);
         printf("  result0.uw[2] = %u (expected %u)\n", result0.uw[2], 4321);
         printf("  result0.uw[3] = %u (expected %u)\n", result0.uw[3], 65535);
      }
   }
   else
   {
      printf("pinsrw_4 ... failed\n");
   }

   return;
}

static void pmaxsw_1(void)
{
   reg64_t arg0 = { .sw = { -1, 2, -3, 4 } };
   reg64_t arg1 = { .sw = { 2, -3, 4, -5 } };
   reg64_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %1, %%mm6\n"
         "movq %2, %%mm7\n"
         "pmaxsw %%mm6, %%mm7\n"
         "movq %%mm7, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg0), "m" (arg1), "m" (state[0])
         : "mm6", "mm7"
      );

      if (result0.sw[0] == 2 && result0.sw[1] == 2 && result0.sw[2] == 4 && result0.sw[3] == 4 )
      {
         printf("pmaxsw_1 ... ok\n");
      }
      else
      {
         printf("pmaxsw_1 ... not ok\n");
         printf("  result0.sw[0] = %d (expected %d)\n", result0.sw[0], 2);
         printf("  result0.sw[1] = %d (expected %d)\n", result0.sw[1], 2);
         printf("  result0.sw[2] = %d (expected %d)\n", result0.sw[2], 4);
         printf("  result0.sw[3] = %d (expected %d)\n", result0.sw[3], 4);
      }
   }
   else
   {
      printf("pmaxsw_1 ... failed\n");
   }

   return;
}

static void pmaxsw_2(void)
{
   reg64_t arg0 = { .sw = { -1, 2, -3, 4 } };
   reg64_t arg1 = { .sw = { 2, -3, 4, -5 } };
   reg64_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %2, %%mm7\n"
         "pmaxsw %1, %%mm7\n"
         "movq %%mm7, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg0), "m" (arg1), "m" (state[0])
         : "mm6", "mm7"
      );

      if (result0.sw[0] == 2 && result0.sw[1] == 2 && result0.sw[2] == 4 && result0.sw[3] == 4 )
      {
         printf("pmaxsw_2 ... ok\n");
      }
      else
      {
         printf("pmaxsw_2 ... not ok\n");
         printf("  result0.sw[0] = %d (expected %d)\n", result0.sw[0], 2);
         printf("  result0.sw[1] = %d (expected %d)\n", result0.sw[1], 2);
         printf("  result0.sw[2] = %d (expected %d)\n", result0.sw[2], 4);
         printf("  result0.sw[3] = %d (expected %d)\n", result0.sw[3], 4);
      }
   }
   else
   {
      printf("pmaxsw_2 ... failed\n");
   }

   return;
}

static void pmaxub_1(void)
{
   reg64_t arg0 = { .ub = { 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U } };
   reg64_t arg1 = { .ub = { 8U, 7U, 6U, 5U, 4U, 3U, 2U, 1U } };
   reg64_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %1, %%mm6\n"
         "movq %2, %%mm7\n"
         "pmaxub %%mm6, %%mm7\n"
         "movq %%mm7, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg0), "m" (arg1), "m" (state[0])
         : "mm6", "mm7"
      );

      if (result0.ub[0] == 8U && result0.ub[1] == 7U && result0.ub[2] == 6U && result0.ub[3] == 5U && result0.ub[4] == 5U && result0.ub[5] == 6U && result0.ub[6] == 7U && result0.ub[7] == 8U )
      {
         printf("pmaxub_1 ... ok\n");
      }
      else
      {
         printf("pmaxub_1 ... not ok\n");
         printf("  result0.ub[0] = %u (expected %u)\n", result0.ub[0], 8U);
         printf("  result0.ub[1] = %u (expected %u)\n", result0.ub[1], 7U);
         printf("  result0.ub[2] = %u (expected %u)\n", result0.ub[2], 6U);
         printf("  result0.ub[3] = %u (expected %u)\n", result0.ub[3], 5U);
         printf("  result0.ub[4] = %u (expected %u)\n", result0.ub[4], 5U);
         printf("  result0.ub[5] = %u (expected %u)\n", result0.ub[5], 6U);
         printf("  result0.ub[6] = %u (expected %u)\n", result0.ub[6], 7U);
         printf("  result0.ub[7] = %u (expected %u)\n", result0.ub[7], 8U);
      }
   }
   else
   {
      printf("pmaxub_1 ... failed\n");
   }

   return;
}

static void pmaxub_2(void)
{
   reg64_t arg0 = { .ub = { 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U } };
   reg64_t arg1 = { .ub = { 8U, 7U, 6U, 5U, 4U, 3U, 2U, 1U } };
   reg64_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %2, %%mm7\n"
         "pmaxub %1, %%mm7\n"
         "movq %%mm7, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg0), "m" (arg1), "m" (state[0])
         : "mm6", "mm7"
      );

      if (result0.ub[0] == 8U && result0.ub[1] == 7U && result0.ub[2] == 6U && result0.ub[3] == 5U && result0.ub[4] == 5U && result0.ub[5] == 6U && result0.ub[6] == 7U && result0.ub[7] == 8U )
      {
         printf("pmaxub_2 ... ok\n");
      }
      else
      {
         printf("pmaxub_2 ... not ok\n");
         printf("  result0.ub[0] = %u (expected %u)\n", result0.ub[0], 8U);
         printf("  result0.ub[1] = %u (expected %u)\n", result0.ub[1], 7U);
         printf("  result0.ub[2] = %u (expected %u)\n", result0.ub[2], 6U);
         printf("  result0.ub[3] = %u (expected %u)\n", result0.ub[3], 5U);
         printf("  result0.ub[4] = %u (expected %u)\n", result0.ub[4], 5U);
         printf("  result0.ub[5] = %u (expected %u)\n", result0.ub[5], 6U);
         printf("  result0.ub[6] = %u (expected %u)\n", result0.ub[6], 7U);
         printf("  result0.ub[7] = %u (expected %u)\n", result0.ub[7], 8U);
      }
   }
   else
   {
      printf("pmaxub_2 ... failed\n");
   }

   return;
}

static void pminsw_1(void)
{
   reg64_t arg0 = { .sw = { -1, 2, -3, 4 } };
   reg64_t arg1 = { .sw = { 2, -3, 4, -5 } };
   reg64_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %1, %%mm6\n"
         "movq %2, %%mm7\n"
         "pminsw %%mm6, %%mm7\n"
         "movq %%mm7, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg0), "m" (arg1), "m" (state[0])
         : "mm6", "mm7"
      );

      if (result0.sw[0] == -1 && result0.sw[1] == -3 && result0.sw[2] == -3 && result0.sw[3] == -5 )
      {
         printf("pminsw_1 ... ok\n");
      }
      else
      {
         printf("pminsw_1 ... not ok\n");
         printf("  result0.sw[0] = %d (expected %d)\n", result0.sw[0], -1);
         printf("  result0.sw[1] = %d (expected %d)\n", result0.sw[1], -3);
         printf("  result0.sw[2] = %d (expected %d)\n", result0.sw[2], -3);
         printf("  result0.sw[3] = %d (expected %d)\n", result0.sw[3], -5);
      }
   }
   else
   {
      printf("pminsw_1 ... failed\n");
   }

   return;
}

static void pminsw_2(void)
{
   reg64_t arg0 = { .sw = { -1, 2, -3, 4 } };
   reg64_t arg1 = { .sw = { 2, -3, 4, -5 } };
   reg64_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %2, %%mm7\n"
         "pminsw %1, %%mm7\n"
         "movq %%mm7, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg0), "m" (arg1), "m" (state[0])
         : "mm6", "mm7"
      );

      if (result0.sw[0] == -1 && result0.sw[1] == -3 && result0.sw[2] == -3 && result0.sw[3] == -5 )
      {
         printf("pminsw_2 ... ok\n");
      }
      else
      {
         printf("pminsw_2 ... not ok\n");
         printf("  result0.sw[0] = %d (expected %d)\n", result0.sw[0], -1);
         printf("  result0.sw[1] = %d (expected %d)\n", result0.sw[1], -3);
         printf("  result0.sw[2] = %d (expected %d)\n", result0.sw[2], -3);
         printf("  result0.sw[3] = %d (expected %d)\n", result0.sw[3], -5);
      }
   }
   else
   {
      printf("pminsw_2 ... failed\n");
   }

   return;
}

static void pminub_1(void)
{
   reg64_t arg0 = { .ub = { 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U } };
   reg64_t arg1 = { .ub = { 8U, 7U, 6U, 5U, 4U, 3U, 2U, 1U } };
   reg64_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %1, %%mm6\n"
         "movq %2, %%mm7\n"
         "pminub %%mm6, %%mm7\n"
         "movq %%mm7, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg0), "m" (arg1), "m" (state[0])
         : "mm6", "mm7"
      );

      if (result0.ub[0] == 1U && result0.ub[1] == 2U && result0.ub[2] == 3U && result0.ub[3] == 4U && result0.ub[4] == 4U && result0.ub[5] == 3U && result0.ub[6] == 2U && result0.ub[7] == 1U )
      {
         printf("pminub_1 ... ok\n");
      }
      else
      {
         printf("pminub_1 ... not ok\n");
         printf("  result0.ub[0] = %u (expected %u)\n", result0.ub[0], 1U);
         printf("  result0.ub[1] = %u (expected %u)\n", result0.ub[1], 2U);
         printf("  result0.ub[2] = %u (expected %u)\n", result0.ub[2], 3U);
         printf("  result0.ub[3] = %u (expected %u)\n", result0.ub[3], 4U);
         printf("  result0.ub[4] = %u (expected %u)\n", result0.ub[4], 4U);
         printf("  result0.ub[5] = %u (expected %u)\n", result0.ub[5], 3U);
         printf("  result0.ub[6] = %u (expected %u)\n", result0.ub[6], 2U);
         printf("  result0.ub[7] = %u (expected %u)\n", result0.ub[7], 1U);
      }
   }
   else
   {
      printf("pminub_1 ... failed\n");
   }

   return;
}

static void pminub_2(void)
{
   reg64_t arg0 = { .ub = { 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U } };
   reg64_t arg1 = { .ub = { 8U, 7U, 6U, 5U, 4U, 3U, 2U, 1U } };
   reg64_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %2, %%mm7\n"
         "pminub %1, %%mm7\n"
         "movq %%mm7, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg0), "m" (arg1), "m" (state[0])
         : "mm6", "mm7"
      );

      if (result0.ub[0] == 1U && result0.ub[1] == 2U && result0.ub[2] == 3U && result0.ub[3] == 4U && result0.ub[4] == 4U && result0.ub[5] == 3U && result0.ub[6] == 2U && result0.ub[7] == 1U )
      {
         printf("pminub_2 ... ok\n");
      }
      else
      {
         printf("pminub_2 ... not ok\n");
         printf("  result0.ub[0] = %u (expected %u)\n", result0.ub[0], 1U);
         printf("  result0.ub[1] = %u (expected %u)\n", result0.ub[1], 2U);
         printf("  result0.ub[2] = %u (expected %u)\n", result0.ub[2], 3U);
         printf("  result0.ub[3] = %u (expected %u)\n", result0.ub[3], 4U);
         printf("  result0.ub[4] = %u (expected %u)\n", result0.ub[4], 4U);
         printf("  result0.ub[5] = %u (expected %u)\n", result0.ub[5], 3U);
         printf("  result0.ub[6] = %u (expected %u)\n", result0.ub[6], 2U);
         printf("  result0.ub[7] = %u (expected %u)\n", result0.ub[7], 1U);
      }
   }
   else
   {
      printf("pminub_2 ... failed\n");
   }

   return;
}

static void pmovmskb_1(void)
{
   reg64_t arg0 = { .uq = { 0x8000000080008088ULL } };
   reg32_t arg1 = { .ud = { 0UL } };
   reg32_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %1, %%mm6\n"
         "movl %2, %%eax\n"
         "pmovmskb %%mm6, %%eax\n"
         "movl %%eax, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg0), "m" (arg1), "m" (state[0])
         : "mm6", "eax"
      );

      if (result0.ud[0] == 0x8bUL )
      {
         printf("pmovmskb_1 ... ok\n");
      }
      else
      {
         printf("pmovmskb_1 ... not ok\n");
         printf("  result0.ud[0] = %lu (expected %lu)\n", result0.ud[0], 0x8bUL);
      }
   }
   else
   {
      printf("pmovmskb_1 ... failed\n");
   }

   return;
}

static void pmulhuw_1(void)
{
   reg64_t arg0 = { .uw = { 1111, 2222, 3333, 4444 } };
   reg64_t arg1 = { .uw = { 5555, 6666, 7777, 8888 } };
   reg64_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %1, %%mm6\n"
         "movq %2, %%mm7\n"
         "pmulhuw %%mm6, %%mm7\n"
         "movq %%mm7, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg0), "m" (arg1), "m" (state[0])
         : "mm6", "mm7"
      );

      if (result0.uw[0] == 0x005e && result0.uw[1] == 0x00e2 && result0.uw[2] == 0x018b && result0.uw[3] == 0x025a )
      {
         printf("pmulhuw_1 ... ok\n");
      }
      else
      {
         printf("pmulhuw_1 ... not ok\n");
         printf("  result0.uw[0] = %u (expected %u)\n", result0.uw[0], 0x005e);
         printf("  result0.uw[1] = %u (expected %u)\n", result0.uw[1], 0x00e2);
         printf("  result0.uw[2] = %u (expected %u)\n", result0.uw[2], 0x018b);
         printf("  result0.uw[3] = %u (expected %u)\n", result0.uw[3], 0x025a);
      }
   }
   else
   {
      printf("pmulhuw_1 ... failed\n");
   }

   return;
}

static void pmulhuw_2(void)
{
   reg64_t arg0 = { .uw = { 1111, 2222, 3333, 4444 } };
   reg64_t arg1 = { .uw = { 5555, 6666, 7777, 8888 } };
   reg64_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %2, %%mm7\n"
         "pmulhuw %1, %%mm7\n"
         "movq %%mm7, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg0), "m" (arg1), "m" (state[0])
         : "mm6", "mm7"
      );

      if (result0.uw[0] == 0x005e && result0.uw[1] == 0x00e2 && result0.uw[2] == 0x018b && result0.uw[3] == 0x025a )
      {
         printf("pmulhuw_2 ... ok\n");
      }
      else
      {
         printf("pmulhuw_2 ... not ok\n");
         printf("  result0.uw[0] = %u (expected %u)\n", result0.uw[0], 0x005e);
         printf("  result0.uw[1] = %u (expected %u)\n", result0.uw[1], 0x00e2);
         printf("  result0.uw[2] = %u (expected %u)\n", result0.uw[2], 0x018b);
         printf("  result0.uw[3] = %u (expected %u)\n", result0.uw[3], 0x025a);
      }
   }
   else
   {
      printf("pmulhuw_2 ... failed\n");
   }

   return;
}

static void psadbw_1(void)
{
   reg64_t arg0 = { .ub = { 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U } };
   reg64_t arg1 = { .ub = { 8U, 7U, 6U, 5U, 4U, 3U, 2U, 1U } };
   reg64_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %1, %%mm6\n"
         "movq %2, %%mm7\n"
         "psadbw %%mm6, %%mm7\n"
         "movq %%mm7, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg0), "m" (arg1), "m" (state[0])
         : "mm6", "mm7"
      );

      if (result0.sw[0] == 32 && result0.sw[1] == 0 && result0.sw[2] == 0 && result0.sw[3] == 0 )
      {
         printf("psadbw_1 ... ok\n");
      }
      else
      {
         printf("psadbw_1 ... not ok\n");
         printf("  result0.sw[0] = %d (expected %d)\n", result0.sw[0], 32);
         printf("  result0.sw[1] = %d (expected %d)\n", result0.sw[1], 0);
         printf("  result0.sw[2] = %d (expected %d)\n", result0.sw[2], 0);
         printf("  result0.sw[3] = %d (expected %d)\n", result0.sw[3], 0);
      }
   }
   else
   {
      printf("psadbw_1 ... failed\n");
   }

   return;
}

static void psadbw_2(void)
{
   reg64_t arg0 = { .ub = { 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U } };
   reg64_t arg1 = { .ub = { 8U, 7U, 6U, 5U, 4U, 3U, 2U, 1U } };
   reg64_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %2, %%mm7\n"
         "psadbw %1, %%mm7\n"
         "movq %%mm7, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg0), "m" (arg1), "m" (state[0])
         : "mm6", "mm7"
      );

      if (result0.sw[0] == 32 && result0.sw[1] == 0 && result0.sw[2] == 0 && result0.sw[3] == 0 )
      {
         printf("psadbw_2 ... ok\n");
      }
      else
      {
         printf("psadbw_2 ... not ok\n");
         printf("  result0.sw[0] = %d (expected %d)\n", result0.sw[0], 32);
         printf("  result0.sw[1] = %d (expected %d)\n", result0.sw[1], 0);
         printf("  result0.sw[2] = %d (expected %d)\n", result0.sw[2], 0);
         printf("  result0.sw[3] = %d (expected %d)\n", result0.sw[3], 0);
      }
   }
   else
   {
      printf("psadbw_2 ... failed\n");
   }

   return;
}

static void pshufw_1(void)
{
   reg64_t arg1 = { .sw = { 11, 22, 33, 44 } };
   reg64_t arg2 = { .sw = { 0, 0, 0, 0 } };
   reg64_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %1, %%mm6\n"
         "movq %2, %%mm7\n"
         "pshufw $0x1b, %%mm6, %%mm7\n"
         "movq %%mm7, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg1), "m" (arg2), "m" (state[0])
         : "mm6", "mm7"
      );

      if (result0.sw[0] == 44 && result0.sw[1] == 33 && result0.sw[2] == 22 && result0.sw[3] == 11 )
      {
         printf("pshufw_1 ... ok\n");
      }
      else
      {
         printf("pshufw_1 ... not ok\n");
         printf("  result0.sw[0] = %d (expected %d)\n", result0.sw[0], 44);
         printf("  result0.sw[1] = %d (expected %d)\n", result0.sw[1], 33);
         printf("  result0.sw[2] = %d (expected %d)\n", result0.sw[2], 22);
         printf("  result0.sw[3] = %d (expected %d)\n", result0.sw[3], 11);
      }
   }
   else
   {
      printf("pshufw_1 ... failed\n");
   }

   return;
}

static void pshufw_2(void)
{
   reg64_t arg1 = { .sw = { 11, 22, 33, 44 } };
   reg64_t arg2 = { .sw = { 0, 0, 0, 0 } };
   reg64_t result0;
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %3\n"
         "movq %2, %%mm7\n"
         "pshufw $0x1b, %1, %%mm7\n"
         "movq %%mm7, %0\n"
         "frstor %3\n"
         "cld\n"
         : "=m" (result0)
         : "m" (arg1), "m" (arg2), "m" (state[0])
         : "mm6", "mm7"
      );

      if (result0.sw[0] == 44 && result0.sw[1] == 33 && result0.sw[2] == 22 && result0.sw[3] == 11 )
      {
         printf("pshufw_2 ... ok\n");
      }
      else
      {
         printf("pshufw_2 ... not ok\n");
         printf("  result0.sw[0] = %d (expected %d)\n", result0.sw[0], 44);
         printf("  result0.sw[1] = %d (expected %d)\n", result0.sw[1], 33);
         printf("  result0.sw[2] = %d (expected %d)\n", result0.sw[2], 22);
         printf("  result0.sw[3] = %d (expected %d)\n", result0.sw[3], 11);
      }
   }
   else
   {
      printf("pshufw_2 ... failed\n");
   }

   return;
}

static void sfence_1(void)
{
   char state[108];

   if (sigsetjmp(catchpoint, 1) == 0)
   {
      asm(
         "fsave %0\n"
         "sfence\n"
         "frstor %0\n"
         "cld\n"
         :
         : "m" (state[0])

      );

      printf("sfence_1 ... ok\n");
   }
   else
   {
      printf("sfence_1 ... failed\n");
   }

   return;
}

int main(int argc, char **argv)
{
   signal(SIGILL, handle_sigill);

   movntq_1();
   pavgb_1();
   pavgb_2();
   pavgw_1();
   pavgw_2();
   pextrw_1();
   pextrw_2();
   pextrw_3();
   pextrw_4();
   pinsrw_1();
   pinsrw_2();
   pinsrw_3();
   pinsrw_4();
   pmaxsw_1();
   pmaxsw_2();
   pmaxub_1();
   pmaxub_2();
   pminsw_1();
   pminsw_2();
   pminub_1();
   pminub_2();
   pmovmskb_1();
   pmulhuw_1();
   pmulhuw_2();
   psadbw_1();
   psadbw_2();
   pshufw_1();
   pshufw_2();
   sfence_1();

   exit(0);
}
