1/* { dg-do run { target i?86-*-* x86_64-*-* } } */
2/* { dg-options "-O2 -msse" } */
3#include <xmmintrin.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <string.h>
7#include "../../gcc.dg/i386-cpuid.h"
8
9#ifndef NOINLINE
10#define NOINLINE __attribute__ ((noinline))
11#endif
12
13#define SHIFT (4)
14
15typedef union {
16  __m64 v;
17  unsigned char c[8];
18  unsigned short int s[4];
19  unsigned long long t;
20  unsigned int u[2];
21}vecInWord;
22
23void sse_tests (void) NOINLINE;
24void dump64_16 (char *, char *, vecInWord);
25int check (const char *, const char *[]);
26
27char buf[8000];
28char comparison[8000];
29static int errors = 0;
30
31vecInWord c64, e64;
32__m64 m64_64;
33
34const char *reference_sse[] = {
35  "_mm_shuffle_pi16 0123 4567 89ab cdef \n",
36  ""
37};
38
39int main()
40{
41  unsigned long cpu_facilities;
42
43  cpu_facilities = i386_cpuid ();
44
45  if ((cpu_facilities & (bit_MMX | bit_SSE | bit_CMOV))
46      != (bit_MMX | bit_SSE | bit_CMOV))
47    /* If host has no vector support, pass.  */
48    exit (0);
49
50  e64.t  = 0x0123456789abcdefULL;
51
52  m64_64 = e64.v;
53
54  if (cpu_facilities & bit_SSE)
55    {
56      sse_tests();
57      check (buf, reference_sse);
58#ifdef DEBUG
59      printf ("sse testing:\n");
60      printf (buf);
61      printf ("\ncomparison:\n");
62      printf (comparison);
63#endif
64      buf[0] = '\0';
65    }
66
67  if (errors != 0)
68    abort ();
69  exit (0);
70}
71
72void NOINLINE
73sse_tests (void)
74{
75  /* pshufw */
76  c64.v = _mm_shuffle_pi16 (m64_64, 0x1b);
77  dump64_16 (buf, "_mm_shuffle_pi16", c64);
78}
79
80void
81dump64_16 (char *buf, char *name, vecInWord x)
82{
83  int i;
84  char *p = buf + strlen (buf);
85
86  sprintf (p, "%s ", name);
87  p += strlen (p);
88
89  for (i=0; i<4; i++)
90    {
91      sprintf (p, "%4.4x ", x.s[i]);
92      p += strlen (p);
93    }
94  strcat (p, "\n");
95}
96
97int
98check (const char *input, const char *reference[])
99{
100  int broken, i, j, len;
101  const char *p_input;
102  char *p_comparison;
103  int new_errors = 0;
104
105  p_comparison = &comparison[0];
106  p_input = input;
107
108  for (i = 0; *reference[i] != '\0'; i++)
109    {
110      broken = 0;
111      len = strlen (reference[i]);
112      for (j = 0; j < len; j++)
113	{
114	  /* Ignore the terminating NUL characters at the end of every string in 'reference[]'.  */
115	  if (!broken && *p_input != reference[i][j])
116	    {
117	      *p_comparison = '\0';
118	      strcat (p_comparison, " >>> ");
119	      p_comparison += strlen (p_comparison);
120	      new_errors++;
121	      broken = 1;
122	    }
123	  *p_comparison = *p_input;
124	  p_comparison++;
125	  p_input++;
126	}
127      if (broken)
128	{
129	  *p_comparison = '\0';
130	  strcat (p_comparison, "expected:\n");
131	  strcat (p_comparison, reference[i]);
132	  p_comparison += strlen (p_comparison);
133	}
134    }
135  *p_comparison = '\0';
136  strcat (p_comparison, new_errors ? "failure\n\n" : "O.K.\n\n") ;
137  errors += new_errors;
138  return 0;
139}
140