blob: 79077982552cb40a2eac0482780e65564c7d3fcb [file] [log] [blame]
#include <altivec.h>
/* Test various ways of creating vectors with 2 double words and accessing the
elements. This include files supports:
testing double
testing long on 64-bit systems
testing long long on 32-bit systems.
The endian support is:
big endian
little endian. */
#ifdef DEBUG
#include <stdio.h>
#define DEBUG0(STR) fputs (STR, stdout)
#define DEBUG2(STR,A,B) printf (STR, A, B)
static int errors = 0;
#else
#include <stdlib.h>
#define DEBUG0(STR)
#define DEBUG2(STR,A,B)
#endif
#if defined(DO_DOUBLE)
#define TYPE double
#define STYPE "double"
#define ZERO 0.0
#define ONE 1.0
#define TWO 2.0
#define THREE 3.0
#define FOUR 4.0
#define FIVE 5.0
#define SIX 6.0
#define FMT "g"
#elif defined(_ARCH_PPC64)
#define TYPE long
#define STYPE "long"
#define ZERO 0L
#define ONE 1L
#define TWO 2L
#define THREE 3L
#define FOUR 4L
#define FIVE 5L
#define SIX 6L
#define FMT "ld"
#else
#define TYPE long long
#define STYPE "long long"
#define ZERO 0LL
#define ONE 1LL
#define TWO 2LL
#define THREE 3LL
#define FOUR 4LL
#define FIVE 5LL
#define SIX 6LL
#define FMT "lld"
#endif
/* Macros to order the left/right values correctly. */
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define INIT_ORDER(A, B) (TYPE) A, (TYPE) B
#define ELEMENT_ORDER(A, B) (TYPE) A, (TYPE) B
#define ENDIAN "-mbig"
#else
#define INIT_ORDER(A, B) (TYPE) B, (TYPE) A
#define ELEMENT_ORDER(A, B) (TYPE) B, (TYPE) A
#define ENDIAN "-mlittle"
#endif
static volatile TYPE five = FIVE;
static volatile TYPE six = SIX;
static volatile vector TYPE s_v12 = { ONE, TWO };
static volatile vector TYPE g_v34 = { THREE, FOUR };
__attribute__((__noinline__))
static void
vector_check (vector TYPE v, TYPE expect_hi, TYPE expect_lo)
{
TYPE actual_hi, actual_lo;
#ifdef DEBUG
const char *pass_fail;
#endif
__asm__ ("xxlor %x0,%x1,%x1" : "=&wa" (actual_hi) : "wa" (v));
__asm__ ("xxpermdi %x0,%x1,%x1,3" : "=&wa" (actual_lo) : "wa" (v));
#ifdef DEBUG
if ((actual_hi == expect_hi) && (actual_lo == expect_lo))
pass_fail = ", pass";
else
{
pass_fail = ", fail";
errors++;
}
printf ("Expected %" FMT ", %" FMT ", got %" FMT ", %" FMT "%s\n",
expect_hi, expect_lo,
actual_hi, actual_lo,
pass_fail);
#else
if ((actual_hi != expect_hi) || (actual_lo != expect_lo))
abort ();
#endif
}
__attribute__((__noinline__))
static vector TYPE
combine (TYPE op0, TYPE op1)
{
return (vector TYPE) { op0, op1 };
}
__attribute__((__noinline__))
static vector TYPE
combine_insert (TYPE op0, TYPE op1)
{
vector TYPE ret = (vector TYPE) { ZERO, ZERO };
ret = vec_insert (op0, ret, 0);
ret = vec_insert (op1, ret, 1);
return ret;
}
__attribute__((__noinline__))
static vector TYPE
concat_extract_00 (vector TYPE a, vector TYPE b)
{
return (vector TYPE) { vec_extract (a, 0), vec_extract (b, 0) };
}
__attribute__((__noinline__))
static vector TYPE
concat_extract_01 (vector TYPE a, vector TYPE b)
{
return (vector TYPE) { vec_extract (a, 0), vec_extract (b, 1) };
}
__attribute__((__noinline__))
static vector TYPE
concat_extract_10 (vector TYPE a, vector TYPE b)
{
return (vector TYPE) { vec_extract (a, 1), vec_extract (b, 0) };
}
__attribute__((__noinline__))
static vector TYPE
concat_extract_11 (vector TYPE a, vector TYPE b)
{
return (vector TYPE) { vec_extract (a, 1), vec_extract (b, 1) };
}
__attribute__((__noinline__))
static vector TYPE
concat_extract2_0s (vector TYPE a, TYPE b)
{
return (vector TYPE) { vec_extract (a, 0), b };
}
__attribute__((__noinline__))
static vector TYPE
concat_extract2_1s (vector TYPE a, TYPE b)
{
return (vector TYPE) { vec_extract (a, 1), b };
}
__attribute__((__noinline__))
static vector TYPE
concat_extract2_s0 (TYPE a, vector TYPE b)
{
return (vector TYPE) { a, vec_extract (b, 0) };
}
__attribute__((__noinline__))
static vector TYPE
concat_extract2_s1 (TYPE a, vector TYPE b)
{
return (vector TYPE) { a, vec_extract (b, 1) };
}
__attribute__((__noinline__))
static vector TYPE
concat_extract_nn (vector TYPE a, vector TYPE b, size_t i, size_t j)
{
return (vector TYPE) { vec_extract (a, i), vec_extract (b, j) };
}
__attribute__((__noinline__))
static vector TYPE
array_0 (vector TYPE v, TYPE a)
{
v[0] = a;
return v;
}
__attribute__((__noinline__))
static vector TYPE
array_1 (vector TYPE v, TYPE a)
{
v[1] = a;
return v;
}
__attribute__((__noinline__))
static vector TYPE
array_01 (vector TYPE v, TYPE a, TYPE b)
{
v[0] = a;
v[1] = b;
return v;
}
__attribute__((__noinline__))
static vector TYPE
array_01b (TYPE a, TYPE b)
{
vector TYPE v = (vector TYPE) { 0, 0 };
v[0] = a;
v[1] = b;
return v;
}
int
main (void)
{
vector TYPE a = (vector TYPE) { ONE, TWO };
vector TYPE b = (vector TYPE) { THREE, FOUR };
size_t i, j;
vector TYPE z = (vector TYPE) { ZERO, ZERO };
DEBUG2 ("Endian: %s, type: %s\n", ENDIAN, STYPE);
DEBUG0 ("\nStatic/global initialization\n");
vector_check (s_v12, INIT_ORDER (1, 2));
vector_check (g_v34, INIT_ORDER (3, 4));
DEBUG0 ("\nVector via constant runtime intiialization\n");
vector_check (a, INIT_ORDER (1, 2));
vector_check (b, INIT_ORDER (3, 4));
DEBUG0 ("\nCombine scalars using vector initialization\n");
vector_check (combine (1, 2), INIT_ORDER (1, 2));
vector_check (combine (3, 4), INIT_ORDER (3, 4));
DEBUG0 ("\nSetup with vec_insert\n");
a = combine_insert (1, 2);
b = combine_insert (3, 4);
vector_check (a, ELEMENT_ORDER (1, 2));
vector_check (b, ELEMENT_ORDER (3, 4));
DEBUG0 ("\nTesting array syntax\n");
vector_check (array_0 (a, FIVE), ELEMENT_ORDER (5, 2));
vector_check (array_1 (b, SIX), ELEMENT_ORDER (3, 6));
vector_check (array_01 (z, FIVE, SIX), ELEMENT_ORDER (5, 6));
vector_check (array_01b (FIVE, SIX), ELEMENT_ORDER (5, 6));
vector_check (array_0 (a, five), ELEMENT_ORDER (5, 2));
vector_check (array_1 (b, six), ELEMENT_ORDER (3, 6));
vector_check (array_01 (z, five, six), ELEMENT_ORDER (5, 6));
vector_check (array_01b (five, six), ELEMENT_ORDER (5, 6));
DEBUG0 ("\nTesting concat and extract\n");
vector_check (concat_extract_00 (a, b), INIT_ORDER (1, 3));
vector_check (concat_extract_01 (a, b), INIT_ORDER (1, 4));
vector_check (concat_extract_10 (a, b), INIT_ORDER (2, 3));
vector_check (concat_extract_11 (a, b), INIT_ORDER (2, 4));
DEBUG0 ("\nTesting concat and extract #2\n");
vector_check (concat_extract2_0s (a, FIVE), INIT_ORDER (1, 5));
vector_check (concat_extract2_1s (a, FIVE), INIT_ORDER (2, 5));
vector_check (concat_extract2_s0 (SIX, a), INIT_ORDER (6, 1));
vector_check (concat_extract2_s1 (SIX, a), INIT_ORDER (6, 2));
DEBUG0 ("\nTesting variable concat and extract\n");
for (i = 0; i < 2; i++)
{
for (j = 0; j < 2; j++)
{
static struct {
TYPE hi;
TYPE lo;
} hilo[2][2] =
{ { { ONE, THREE }, { ONE, FOUR } },
{ { TWO, THREE }, { TWO, FOUR } } };
vector_check (concat_extract_nn (a, b, i, j),
INIT_ORDER (hilo[i][j].hi, hilo[i][j].lo));
}
}
DEBUG0 ("\nTesting separate function\n");
vector_check (combine (vec_extract (a, 0), vec_extract (b, 0)),
INIT_ORDER (1, 3));
vector_check (combine (vec_extract (a, 0), vec_extract (b, 1)),
INIT_ORDER (1, 4));
vector_check (combine (vec_extract (a, 1), vec_extract (b, 0)),
INIT_ORDER (2, 3));
vector_check (combine (vec_extract (a, 1), vec_extract (b, 1)),
INIT_ORDER (2, 4));
vector_check (combine_insert (vec_extract (a, 0), vec_extract (b, 0)),
ELEMENT_ORDER (1, 3));
vector_check (combine_insert (vec_extract (a, 0), vec_extract (b, 1)),
ELEMENT_ORDER (1, 4));
vector_check (combine_insert (vec_extract (a, 1), vec_extract (b, 0)),
ELEMENT_ORDER (2, 3));
vector_check (combine_insert (vec_extract (a, 1), vec_extract (b, 1)),
ELEMENT_ORDER (2, 4));
#if defined(DO_DOUBLE)
DEBUG0 ("\nTesting explicit 2df concat\n");
vector_check (__builtin_vsx_concat_2df (FIVE, SIX), INIT_ORDER (5, 6));
vector_check (__builtin_vsx_concat_2df (five, six), INIT_ORDER (5, 6));
#elif defined(_ARCH_PPC64)
DEBUG0 ("\nTesting explicit 2di concat\n");
vector_check (__builtin_vsx_concat_2di (FIVE, SIX), INIT_ORDER (5, 6));
vector_check (__builtin_vsx_concat_2di (five, six), INIT_ORDER (5, 6));
#else
DEBUG0 ("\nSkip explicit 2di concat on 32-bit\n");
#endif
#ifdef DEBUG
if (errors)
printf ("\n%d error%s were found", errors, (errors == 1) ? "" : "s");
else
printf ("\nNo errors were found.\n");
return errors;
#else
return 0;
#endif
}