| /* { 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; |
| } |