1258945Sroberto/* { dg-do run { target i?86-*-* x86_64-*-* } } */
2258945Sroberto/* { dg-options "-O2 -mmmx" } */
3258945Sroberto#include <mmintrin.h>
4258945Sroberto#include <stdio.h>
5258945Sroberto#include <stdlib.h>
6258945Sroberto#include <string.h>
7258945Sroberto#include "../../gcc.dg/i386-cpuid.h"
8258945Sroberto
9258945Sroberto#ifndef NOINLINE
10258945Sroberto#define NOINLINE __attribute__ ((noinline))
11258945Sroberto#endif
12258945Sroberto
13258945Sroberto#define SHIFT (4)
14258945Sroberto
15258945Srobertotypedef union {
16258945Sroberto  __m64 v;
17258945Sroberto  unsigned char c[8];
18258945Sroberto  unsigned short int s[4];
19258945Sroberto  unsigned long long t;
20258945Sroberto  unsigned int u[2];
21258945Sroberto}vecInWord;
22258945Sroberto
23258945Srobertovoid mmx_tests (void) NOINLINE;
24258945Srobertovoid dump64_16 (char *, char *, vecInWord);
25258945Srobertovoid dump64_32 (char *, char *, vecInWord);
26258945Srobertovoid dump64_64 (char *, char *, vecInWord);
27258945Srobertoint check (const char *, const char *[]);
28258945Sroberto
29258945Srobertochar buf[8000];
30258945Srobertochar comparison[8000];
31258945Srobertostatic int errors = 0;
32258945Sroberto
33258945SrobertovecInWord a64, b64, c64, d64, e64;
34258945Sroberto__m64 m64_16, s64, m64_32, m64_64;
35258945Sroberto
36258945Srobertoconst char *reference_mmx[] = {
37258945Sroberto  "_mm_srai_pi16 0012 0012 0012 0012 \n",
38258945Sroberto  "_mm_sra_pi16 0012 0012 0012 0012 \n",
39258945Sroberto  "_mm_srai_pi32 00123456 00123456 \n",
40258945Sroberto  "_mm_sra_pi32 00123456 00123456 \n",
41258945Sroberto  "_mm_srli_pi16 0012 0012 0012 0012 \n",
42258945Sroberto  "_mm_srl_pi16 0012 0012 0012 0012 \n",
43258945Sroberto  "_mm_srli_pi32 00123456 00123456 \n",
44258945Sroberto  "_mm_srl_pi32 00123456 00123456 \n",
45258945Sroberto  "_mm_srli_si64 00123456789abcde\n",
46258945Sroberto  "_mm_srl_si64 00123456789abcde\n",
47258945Sroberto  "_mm_slli_pi16 1230 1230 1230 1230 \n",
48258945Sroberto  "_mm_sll_pi16 1230 1230 1230 1230 \n",
49258945Sroberto  "_mm_slli_pi32 12345670 12345670 \n",
50258945Sroberto  "_mm_sll_pi32 12345670 12345670 \n",
51258945Sroberto  "_mm_slli_si64 123456789abcdef0\n",
52258945Sroberto  "_mm_sll_si64 123456789abcdef0\n",
53258945Sroberto  ""
54258945Sroberto};
55258945Sroberto
56258945Srobertoint main()
57258945Sroberto{
58258945Sroberto  unsigned long cpu_facilities;
59258945Sroberto
60258945Sroberto  cpu_facilities = i386_cpuid ();
61258945Sroberto
62258945Sroberto  if ((cpu_facilities & bit_MMX) == 0)
63258945Sroberto    exit (0);
64258945Sroberto
65258945Sroberto  d64.u[0]  = 0x01234567;
66258945Sroberto  d64.u[1]  = 0x01234567;
67258945Sroberto
68258945Sroberto  m64_32 = d64.v;
69258945Sroberto
70258945Sroberto  e64.t  = 0x0123456789abcdefULL;
71258945Sroberto
72258945Sroberto  m64_64 = e64.v;
73258945Sroberto
74258945Sroberto  a64.s[0] = 0x0123;
75258945Sroberto  a64.s[1] = 0x0123;
76258945Sroberto  a64.s[2] = 0x0123;
77258945Sroberto  a64.s[3] = 0x0123;
78258945Sroberto
79258945Sroberto  m64_16 = a64.v;
80258945Sroberto
81258945Sroberto  b64.s[0] = SHIFT;
82258945Sroberto  b64.s[1] = 0;
83258945Sroberto  b64.s[2] = 0;
84258945Sroberto  b64.s[3] = 0;
85258945Sroberto
86258945Sroberto  s64 = b64.v;
87258945Sroberto
88258945Sroberto  if (cpu_facilities & bit_MMX)
89258945Sroberto    {
90258945Sroberto      mmx_tests();
91258945Sroberto      check (buf, reference_mmx);
92258945Sroberto#ifdef DEBUG
93258945Sroberto      printf ("mmx testing:\n");
94258945Sroberto      printf (buf);
95258945Sroberto      printf ("\ncomparison:\n");
96258945Sroberto      printf (comparison);
97258945Sroberto#endif
98258945Sroberto      buf[0] = '\0';
99258945Sroberto    }
100258945Sroberto
101258945Sroberto  if (errors != 0)
102258945Sroberto    abort ();
103258945Sroberto  exit (0);
104258945Sroberto}
105258945Sroberto
106258945Srobertovoid NOINLINE
107258945Srobertommx_tests (void)
108258945Sroberto{
109258945Sroberto  /* psraw */
110258945Sroberto  c64.v = _mm_srai_pi16 (m64_16, SHIFT);
111258945Sroberto  dump64_16 (buf, "_mm_srai_pi16", c64);
112258945Sroberto  c64.v  = _mm_sra_pi16 (m64_16, s64);
113258945Sroberto  dump64_16 (buf, "_mm_sra_pi16", c64);
114258945Sroberto
115258945Sroberto  /* psrad */
116258945Sroberto  c64.v  = _mm_srai_pi32 (m64_32, SHIFT);
117258945Sroberto  dump64_32 (buf, "_mm_srai_pi32", c64);
118258945Sroberto  c64.v = _mm_sra_pi32 (m64_32, s64);
119258945Sroberto  dump64_32 (buf, "_mm_sra_pi32", c64);
120258945Sroberto
121258945Sroberto  /* psrlw */
122258945Sroberto  c64.v = _mm_srli_pi16 (m64_16, SHIFT);
123258945Sroberto  dump64_16 (buf, "_mm_srli_pi16", c64);
124258945Sroberto  c64.v = _mm_srl_pi16 (m64_16, s64);
125258945Sroberto  dump64_16 (buf, "_mm_srl_pi16", c64);
126258945Sroberto
127258945Sroberto  /* psrld */
128258945Sroberto  c64.v = _mm_srli_pi32 (m64_32, SHIFT);
129258945Sroberto  dump64_32 (buf, "_mm_srli_pi32", c64);
130258945Sroberto  c64.v = _mm_srl_pi32 (m64_32, s64);
131258945Sroberto  dump64_32 (buf, "_mm_srl_pi32", c64);
132258945Sroberto
133258945Sroberto  /* psrlq */
134258945Sroberto  c64.v = _mm_srli_si64 (m64_64, SHIFT);
135258945Sroberto  dump64_64 (buf, "_mm_srli_si64", c64);
136258945Sroberto  c64.v = _mm_srl_si64 (m64_64, s64);
137258945Sroberto  dump64_64 (buf, "_mm_srl_si64", c64);
138258945Sroberto
139258945Sroberto  /* psllw */
140258945Sroberto  c64.v = _mm_slli_pi16 (m64_16, SHIFT);
141258945Sroberto  dump64_16 (buf, "_mm_slli_pi16", c64);
142258945Sroberto  c64.v = _mm_sll_pi16 (m64_16, s64);
143258945Sroberto  dump64_16 (buf, "_mm_sll_pi16", c64);
144258945Sroberto
145258945Sroberto  /* pslld */
146258945Sroberto  c64.v = _mm_slli_pi32 (m64_32, SHIFT);
147258945Sroberto  dump64_32 (buf, "_mm_slli_pi32", c64);
148258945Sroberto  c64.v = _mm_sll_pi32 (m64_32, s64);
149258945Sroberto  dump64_32 (buf, "_mm_sll_pi32", c64);
150258945Sroberto
151258945Sroberto  /* psllq */
152258945Sroberto  c64.v = _mm_slli_si64 (m64_64, SHIFT);
153258945Sroberto  dump64_64 (buf, "_mm_slli_si64", c64);
154258945Sroberto  c64.v = _mm_sll_si64 (m64_64, s64);
155258945Sroberto  dump64_64 (buf, "_mm_sll_si64", c64);
156258945Sroberto}
157258945Sroberto
158258945Srobertovoid
159258945Srobertodump64_16 (char *buf, char *name, vecInWord x)
160258945Sroberto{
161258945Sroberto  int i;
162258945Sroberto  char *p = buf + strlen (buf);
163258945Sroberto
164258945Sroberto  sprintf (p, "%s ", name);
165258945Sroberto  p += strlen (p);
166258945Sroberto
167258945Sroberto  for (i=0; i<4; i++)
168258945Sroberto    {
169258945Sroberto      sprintf (p, "%4.4x ", x.s[i]);
170258945Sroberto      p += strlen (p);
171258945Sroberto    }
172258945Sroberto  strcat (p, "\n");
173258945Sroberto}
174258945Sroberto
175258945Srobertovoid
176258945Srobertodump64_32 (char *buf, char *name, vecInWord x)
177258945Sroberto{
178258945Sroberto  int i;
179258945Sroberto  char *p = buf + strlen (buf);
180258945Sroberto
181258945Sroberto  sprintf (p, "%s ", name);
182258945Sroberto  p += strlen (p);
183258945Sroberto
184258945Sroberto  for (i=0; i<2; i++)
185258945Sroberto    {
186258945Sroberto      sprintf (p, "%8.8x ", x.u[i]);
187258945Sroberto      p += strlen (p);
188258945Sroberto    }
189258945Sroberto  strcat (p, "\n");
190258945Sroberto}
191258945Sroberto
192258945Srobertovoid
193258945Srobertodump64_64 (char *buf, char *name, vecInWord x)
194258945Sroberto{
195258945Sroberto  char *p = buf + strlen (buf);
196258945Sroberto
197258945Sroberto  sprintf (p, "%s ", name);
198258945Sroberto  p += strlen (p);
199258945Sroberto
200258945Sroberto  sprintf (p, "%16.16llx\n", x.t);
201258945Sroberto}
202258945Sroberto
203258945Srobertoint
204258945Srobertocheck (const char *input, const char *reference[])
205258945Sroberto{
206258945Sroberto  int broken, i, j, len;
207258945Sroberto  const char *p_input;
208258945Sroberto  char *p_comparison;
209258945Sroberto  int new_errors = 0;
210258945Sroberto
211258945Sroberto  p_comparison = &comparison[0];
212258945Sroberto  p_input = input;
213258945Sroberto
214258945Sroberto  for (i = 0; *reference[i] != '\0'; i++)
215258945Sroberto    {
216258945Sroberto      broken = 0;
217258945Sroberto      len = strlen (reference[i]);
218258945Sroberto      for (j = 0; j < len; j++)
219258945Sroberto	{
220258945Sroberto	  /* Ignore the terminating NUL characters at the end of every string in 'reference[]'.  */
221258945Sroberto	  if (!broken && *p_input != reference[i][j])
222258945Sroberto	    {
223258945Sroberto	      *p_comparison = '\0';
224258945Sroberto	      strcat (p_comparison, " >>> ");
225258945Sroberto	      p_comparison += strlen (p_comparison);
226258945Sroberto	      new_errors++;
227258945Sroberto	      broken = 1;
228258945Sroberto	    }
229258945Sroberto	  *p_comparison = *p_input;
230258945Sroberto	  p_comparison++;
231258945Sroberto	  p_input++;
232258945Sroberto	}
233258945Sroberto      if (broken)
234258945Sroberto	{
235258945Sroberto	  *p_comparison = '\0';
236258945Sroberto	  strcat (p_comparison, "expected:\n");
237258945Sroberto	  strcat (p_comparison, reference[i]);
238258945Sroberto	  p_comparison += strlen (p_comparison);
239258945Sroberto	}
240258945Sroberto    }
241258945Sroberto  *p_comparison = '\0';
242258945Sroberto  strcat (p_comparison, new_errors ? "failure\n\n" : "O.K.\n\n") ;
243258945Sroberto  errors += new_errors;
244258945Sroberto  return 0;
245258945Sroberto}
246258945Sroberto