blob: 071baf7860c7c5ede102b39b22a9d146fe476da9 [file] [log] [blame]
/* { dg-do run { target i?86-*-* x86_64-*-* } } */
/* { dg-options "-O2 -mmmx" } */
#include <mmintrin.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "i386-cpuid.h"
#ifndef NOINLINE
#define NOINLINE __attribute__ ((noinline))
#endif
#define SHIFT (4)
typedef union {
__m64 v;
unsigned char c[8];
unsigned short int s[4];
unsigned long long t;
unsigned int u[2];
}vecInWord;
void mmx_tests (void) NOINLINE;
void dump64_16 (char *, char *, vecInWord);
void dump64_32 (char *, char *, vecInWord);
void dump64_64 (char *, char *, vecInWord);
int check (const char *, const char *[]);
char buf[8000];
char comparison[8000];
static int errors = 0;
vecInWord a64, b64, c64, d64, e64;
__m64 m64_16, s64, m64_32, m64_64;
const char *reference_mmx[] = {
"_mm_srai_pi16 0012 0012 0012 0012 \n",
"_mm_sra_pi16 0012 0012 0012 0012 \n",
"_mm_srai_pi32 00123456 00123456 \n",
"_mm_sra_pi32 00123456 00123456 \n",
"_mm_srli_pi16 0012 0012 0012 0012 \n",
"_mm_srl_pi16 0012 0012 0012 0012 \n",
"_mm_srli_pi32 00123456 00123456 \n",
"_mm_srl_pi32 00123456 00123456 \n",
"_mm_srli_si64 00123456789abcde\n",
"_mm_srl_si64 00123456789abcde\n",
"_mm_slli_pi16 1230 1230 1230 1230 \n",
"_mm_sll_pi16 1230 1230 1230 1230 \n",
"_mm_slli_pi32 12345670 12345670 \n",
"_mm_sll_pi32 12345670 12345670 \n",
"_mm_slli_si64 123456789abcdef0\n",
"_mm_sll_si64 123456789abcdef0\n",
""
};
int main()
{
unsigned long cpu_facilities;
cpu_facilities = i386_cpuid ();
if ((cpu_facilities & bit_MMX) == 0)
exit (0);
d64.u[0] = 0x01234567;
d64.u[1] = 0x01234567;
m64_32 = d64.v;
e64.t = 0x0123456789abcdefULL;
m64_64 = e64.v;
a64.s[0] = 0x0123;
a64.s[1] = 0x0123;
a64.s[2] = 0x0123;
a64.s[3] = 0x0123;
m64_16 = a64.v;
b64.s[0] = SHIFT;
b64.s[1] = 0;
b64.s[2] = 0;
b64.s[3] = 0;
s64 = b64.v;
if (cpu_facilities & bit_MMX)
{
mmx_tests();
check (buf, reference_mmx);
#ifdef DEBUG
printf ("mmx testing:\n");
printf (buf);
printf ("\ncomparison:\n");
printf (comparison);
#endif
buf[0] = '\0';
}
if (errors != 0)
abort ();
exit (0);
}
void NOINLINE
mmx_tests (void)
{
/* psraw */
c64.v = _mm_srai_pi16 (m64_16, SHIFT);
dump64_16 (buf, "_mm_srai_pi16", c64);
c64.v = _mm_sra_pi16 (m64_16, s64);
dump64_16 (buf, "_mm_sra_pi16", c64);
/* psrad */
c64.v = _mm_srai_pi32 (m64_32, SHIFT);
dump64_32 (buf, "_mm_srai_pi32", c64);
c64.v = _mm_sra_pi32 (m64_32, s64);
dump64_32 (buf, "_mm_sra_pi32", c64);
/* psrlw */
c64.v = _mm_srli_pi16 (m64_16, SHIFT);
dump64_16 (buf, "_mm_srli_pi16", c64);
c64.v = _mm_srl_pi16 (m64_16, s64);
dump64_16 (buf, "_mm_srl_pi16", c64);
/* psrld */
c64.v = _mm_srli_pi32 (m64_32, SHIFT);
dump64_32 (buf, "_mm_srli_pi32", c64);
c64.v = _mm_srl_pi32 (m64_32, s64);
dump64_32 (buf, "_mm_srl_pi32", c64);
/* psrlq */
c64.v = _mm_srli_si64 (m64_64, SHIFT);
dump64_64 (buf, "_mm_srli_si64", c64);
c64.v = _mm_srl_si64 (m64_64, s64);
dump64_64 (buf, "_mm_srl_si64", c64);
/* psllw */
c64.v = _mm_slli_pi16 (m64_16, SHIFT);
dump64_16 (buf, "_mm_slli_pi16", c64);
c64.v = _mm_sll_pi16 (m64_16, s64);
dump64_16 (buf, "_mm_sll_pi16", c64);
/* pslld */
c64.v = _mm_slli_pi32 (m64_32, SHIFT);
dump64_32 (buf, "_mm_slli_pi32", c64);
c64.v = _mm_sll_pi32 (m64_32, s64);
dump64_32 (buf, "_mm_sll_pi32", c64);
/* psllq */
c64.v = _mm_slli_si64 (m64_64, SHIFT);
dump64_64 (buf, "_mm_slli_si64", c64);
c64.v = _mm_sll_si64 (m64_64, s64);
dump64_64 (buf, "_mm_sll_si64", c64);
}
void
dump64_16 (char *buf, char *name, vecInWord x)
{
int i;
char *p = buf + strlen (buf);
sprintf (p, "%s ", name);
p += strlen (p);
for (i=0; i<4; i++)
{
sprintf (p, "%4.4x ", x.s[i]);
p += strlen (p);
}
strcat (p, "\n");
}
void
dump64_32 (char *buf, char *name, vecInWord x)
{
int i;
char *p = buf + strlen (buf);
sprintf (p, "%s ", name);
p += strlen (p);
for (i=0; i<2; i++)
{
sprintf (p, "%8.8x ", x.u[i]);
p += strlen (p);
}
strcat (p, "\n");
}
void
dump64_64 (char *buf, char *name, vecInWord x)
{
char *p = buf + strlen (buf);
sprintf (p, "%s ", name);
p += strlen (p);
sprintf (p, "%16.16llx\n", x.t);
}
int
check (const char *input, const char *reference[])
{
int broken, i, j, len;
const char *p_input;
char *p_comparison;
int new_errors = 0;
p_comparison = &comparison[0];
p_input = input;
for (i = 0; *reference[i] != '\0'; i++)
{
broken = 0;
len = strlen (reference[i]);
for (j = 0; j < len; j++)
{
/* Ignore the terminating NUL characters at the end of every string in 'reference[]'. */
if (!broken && *p_input != reference[i][j])
{
*p_comparison = '\0';
strcat (p_comparison, " >>> ");
p_comparison += strlen (p_comparison);
new_errors++;
broken = 1;
}
*p_comparison = *p_input;
p_comparison++;
p_input++;
}
if (broken)
{
*p_comparison = '\0';
strcat (p_comparison, "expected:\n");
strcat (p_comparison, reference[i]);
p_comparison += strlen (p_comparison);
}
}
*p_comparison = '\0';
strcat (p_comparison, new_errors ? "failure\n\n" : "O.K.\n\n") ;
errors += new_errors;
return 0;
}