1 #include <altivec.h>
2 
3 /* Test various ways of creating vectors with 2 double words and accessing the
4    elements.  This include files supports:
5 
6 	 testing double
7 	 testing long on 64-bit systems
8 	 testing long long on 32-bit systems.
9 
10    The endian support is:
11 
12 	big endian
13 	little endian with little endian element ordering
14 	little endian with big endian element ordering.  */
15 
16 #ifdef DEBUG
17 #include <stdio.h>
18 #define DEBUG0(STR)		fputs (STR, stdout)
19 #define DEBUG2(STR,A,B)		printf (STR, A, B)
20 
21 static int errors = 0;
22 
23 #else
24 #include <stdlib.h>
25 #define DEBUG0(STR)
26 #define DEBUG2(STR,A,B)
27 #endif
28 
29 #if defined(DO_DOUBLE)
30 #define TYPE	double
31 #define STYPE	"double"
32 #define ZERO	0.0
33 #define ONE	1.0
34 #define TWO	2.0
35 #define THREE	3.0
36 #define FOUR	4.0
37 #define FIVE	5.0
38 #define SIX	6.0
39 #define FMT	"g"
40 
41 #elif defined(_ARCH_PPC64)
42 #define TYPE	long
43 #define STYPE	"long"
44 #define ZERO	0L
45 #define ONE	1L
46 #define TWO	2L
47 #define THREE	3L
48 #define FOUR	4L
49 #define FIVE	5L
50 #define SIX	6L
51 #define FMT	"ld"
52 
53 #else
54 #define TYPE	long long
55 #define STYPE	"long long"
56 #define ZERO	0LL
57 #define ONE	1LL
58 #define TWO	2LL
59 #define THREE	3LL
60 #define FOUR	4LL
61 #define FIVE	5LL
62 #define SIX	6LL
63 #define FMT	"lld"
64 #endif
65 
66 /* Macros to order the left/right values correctly.  Note, -maltivec=be does
67    not change the order for static initializations, so we have to handle it
68    specially.  */
69 
70 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
71 #define INIT_ORDER(A, B)	(TYPE) A, (TYPE) B
72 #define ELEMENT_ORDER(A, B)	(TYPE) A, (TYPE) B
73 #define ENDIAN			"-mbig"
74 
75 #elif __VEC_ELEMENT_REG_ORDER__ == __ORDER_BIG_ENDIAN__
76 #define NO_ARRAY
77 #define INIT_ORDER(A, B)	(TYPE) B, (TYPE) A
78 #define ELEMENT_ORDER(A, B)	(TYPE) A, (TYPE) B
79 #define ENDIAN			"-mlittle -maltivec=be"
80 
81 #else
82 #define INIT_ORDER(A, B)	(TYPE) B, (TYPE) A
83 #define ELEMENT_ORDER(A, B)	(TYPE) B, (TYPE) A
84 #define ENDIAN			"-mlittle"
85 #endif
86 
87 static volatile TYPE		five	= FIVE;
88 static volatile TYPE		six	= SIX;
89 static volatile vector TYPE	s_v12 = { ONE,   TWO };
90 static volatile vector TYPE	g_v34 = { THREE, FOUR };
91 
92 
93 __attribute__((__noinline__))
94 static void
vector_check(vector TYPE v,TYPE expect_hi,TYPE expect_lo)95 vector_check (vector TYPE v, TYPE expect_hi, TYPE expect_lo)
96 {
97   TYPE actual_hi, actual_lo;
98 #ifdef DEBUG
99   const char *pass_fail;
100 #endif
101 
102   __asm__ ("xxlor %x0,%x1,%x1"		: "=&wa" (actual_hi) : "wa" (v));
103   __asm__ ("xxpermdi %x0,%x1,%x1,3"	: "=&wa" (actual_lo) : "wa" (v));
104 
105 #ifdef DEBUG
106   if ((actual_hi == expect_hi) && (actual_lo == expect_lo))
107     pass_fail = ", pass";
108   else
109     {
110       pass_fail = ", fail";
111       errors++;
112     }
113 
114   printf ("Expected %" FMT ", %" FMT ", got %" FMT ", %" FMT "%s\n",
115 	  expect_hi, expect_lo,
116 	  actual_hi, actual_lo,
117 	  pass_fail);
118 #else
119   if ((actual_hi != expect_hi) || (actual_lo != expect_lo))
120     abort ();
121 #endif
122 }
123 
124 __attribute__((__noinline__))
125 static vector TYPE
combine(TYPE op0,TYPE op1)126 combine (TYPE op0, TYPE op1)
127 {
128   return (vector TYPE) { op0, op1 };
129 }
130 
131 __attribute__((__noinline__))
132 static vector TYPE
combine_insert(TYPE op0,TYPE op1)133 combine_insert (TYPE op0, TYPE op1)
134 {
135   vector TYPE ret = (vector TYPE) { ZERO, ZERO };
136   ret = vec_insert (op0, ret, 0);
137   ret = vec_insert (op1, ret, 1);
138   return ret;
139 }
140 
141 __attribute__((__noinline__))
142 static vector TYPE
concat_extract_00(vector TYPE a,vector TYPE b)143 concat_extract_00 (vector TYPE a, vector TYPE b)
144 {
145   return (vector TYPE) { vec_extract (a, 0), vec_extract (b, 0) };
146 }
147 
148 __attribute__((__noinline__))
149 static vector TYPE
concat_extract_01(vector TYPE a,vector TYPE b)150 concat_extract_01 (vector TYPE a, vector TYPE b)
151 {
152   return (vector TYPE) { vec_extract (a, 0), vec_extract (b, 1) };
153 }
154 
155 __attribute__((__noinline__))
156 static vector TYPE
concat_extract_10(vector TYPE a,vector TYPE b)157 concat_extract_10 (vector TYPE a, vector TYPE b)
158 {
159   return (vector TYPE) { vec_extract (a, 1), vec_extract (b, 0) };
160 }
161 
162 __attribute__((__noinline__))
163 static vector TYPE
concat_extract_11(vector TYPE a,vector TYPE b)164 concat_extract_11 (vector TYPE a, vector TYPE b)
165 {
166   return (vector TYPE) { vec_extract (a, 1), vec_extract (b, 1) };
167 }
168 
169 __attribute__((__noinline__))
170 static vector TYPE
concat_extract2_0s(vector TYPE a,TYPE b)171 concat_extract2_0s (vector TYPE a, TYPE b)
172 {
173   return (vector TYPE) { vec_extract (a, 0), b };
174 }
175 
176 __attribute__((__noinline__))
177 static vector TYPE
concat_extract2_1s(vector TYPE a,TYPE b)178 concat_extract2_1s (vector TYPE a, TYPE b)
179 {
180   return (vector TYPE) { vec_extract (a, 1), b };
181 }
182 
183 __attribute__((__noinline__))
184 static vector TYPE
concat_extract2_s0(TYPE a,vector TYPE b)185 concat_extract2_s0 (TYPE a, vector TYPE b)
186 {
187   return (vector TYPE) { a, vec_extract (b, 0) };
188 }
189 
190 __attribute__((__noinline__))
191 static vector TYPE
concat_extract2_s1(TYPE a,vector TYPE b)192 concat_extract2_s1 (TYPE a, vector TYPE b)
193 {
194   return (vector TYPE) { a, vec_extract (b, 1) };
195 }
196 
197 __attribute__((__noinline__))
198 static vector TYPE
concat_extract_nn(vector TYPE a,vector TYPE b,size_t i,size_t j)199 concat_extract_nn (vector TYPE a, vector TYPE b, size_t i, size_t j)
200 {
201   return (vector TYPE) { vec_extract (a, i), vec_extract (b, j) };
202 }
203 
204 #ifndef NO_ARRAY
205 __attribute__((__noinline__))
206 static vector TYPE
array_0(vector TYPE v,TYPE a)207 array_0 (vector TYPE v, TYPE a)
208 {
209   v[0] = a;
210   return v;
211 }
212 
213 __attribute__((__noinline__))
214 static vector TYPE
array_1(vector TYPE v,TYPE a)215 array_1 (vector TYPE v, TYPE a)
216 {
217   v[1] = a;
218   return v;
219 }
220 
221 __attribute__((__noinline__))
222 static vector TYPE
array_01(vector TYPE v,TYPE a,TYPE b)223 array_01 (vector TYPE v, TYPE a, TYPE b)
224 {
225   v[0] = a;
226   v[1] = b;
227   return v;
228 }
229 
230 __attribute__((__noinline__))
231 static vector TYPE
array_01b(TYPE a,TYPE b)232 array_01b (TYPE a, TYPE b)
233 {
234   vector TYPE v = (vector TYPE) { 0, 0 };
235   v[0] = a;
236   v[1] = b;
237   return v;
238 }
239 #endif
240 
241 int
main(void)242 main (void)
243 {
244   vector TYPE a = (vector TYPE) { ONE,   TWO  };
245   vector TYPE b = (vector TYPE) { THREE, FOUR };
246   size_t i, j;
247 
248 #ifndef NO_ARRAY
249   vector TYPE z = (vector TYPE) { ZERO,  ZERO };
250 #endif
251 
252   DEBUG2 ("Endian: %s, type: %s\n", ENDIAN, STYPE);
253   DEBUG0 ("\nStatic/global initialization\n");
254   vector_check (s_v12, INIT_ORDER (1, 2));
255   vector_check (g_v34, INIT_ORDER (3, 4));
256 
257   DEBUG0 ("\nVector via constant runtime intiialization\n");
258   vector_check (a, INIT_ORDER (1, 2));
259   vector_check (b, INIT_ORDER (3, 4));
260 
261   DEBUG0 ("\nCombine scalars using vector initialization\n");
262   vector_check (combine (1, 2), INIT_ORDER (1, 2));
263   vector_check (combine (3, 4), INIT_ORDER (3, 4));
264 
265   DEBUG0 ("\nSetup with vec_insert\n");
266   a = combine_insert (1, 2);
267   b = combine_insert (3, 4);
268   vector_check (a, ELEMENT_ORDER (1, 2));
269   vector_check (b, ELEMENT_ORDER (3, 4));
270 
271 #ifndef NO_ARRAY
272   DEBUG0 ("\nTesting array syntax\n");
273   vector_check (array_0   (a, FIVE),      ELEMENT_ORDER (5, 2));
274   vector_check (array_1   (b, SIX),       ELEMENT_ORDER (3, 6));
275   vector_check (array_01  (z, FIVE, SIX), ELEMENT_ORDER (5, 6));
276   vector_check (array_01b (FIVE, SIX),    ELEMENT_ORDER (5, 6));
277 
278   vector_check (array_0   (a, five),      ELEMENT_ORDER (5, 2));
279   vector_check (array_1   (b, six),       ELEMENT_ORDER (3, 6));
280   vector_check (array_01  (z, five, six), ELEMENT_ORDER (5, 6));
281   vector_check (array_01b (five, six),    ELEMENT_ORDER (5, 6));
282 #else
283   DEBUG0 ("\nSkipping array syntax on -maltivec=be\n");
284 #endif
285 
286   DEBUG0 ("\nTesting concat and extract\n");
287   vector_check (concat_extract_00 (a, b), INIT_ORDER (1, 3));
288   vector_check (concat_extract_01 (a, b), INIT_ORDER (1, 4));
289   vector_check (concat_extract_10 (a, b), INIT_ORDER (2, 3));
290   vector_check (concat_extract_11 (a, b), INIT_ORDER (2, 4));
291 
292   DEBUG0 ("\nTesting concat and extract #2\n");
293   vector_check (concat_extract2_0s (a, FIVE), INIT_ORDER (1, 5));
294   vector_check (concat_extract2_1s (a, FIVE), INIT_ORDER (2, 5));
295   vector_check (concat_extract2_s0 (SIX, a),  INIT_ORDER (6, 1));
296   vector_check (concat_extract2_s1 (SIX, a),  INIT_ORDER (6, 2));
297 
298   DEBUG0 ("\nTesting variable concat and extract\n");
299   for (i = 0; i < 2; i++)
300     {
301       for (j = 0; j < 2; j++)
302 	{
303 	  static struct {
304 	    TYPE hi;
305 	    TYPE lo;
306 	  } hilo[2][2] =
307 	      { { { ONE, THREE }, { ONE, FOUR } },
308 		{ { TWO, THREE }, { TWO, FOUR } } };
309 
310 	  vector_check (concat_extract_nn (a, b, i, j),
311 			INIT_ORDER (hilo[i][j].hi, hilo[i][j].lo));
312 	}
313     }
314 
315   DEBUG0 ("\nTesting separate function\n");
316   vector_check (combine (vec_extract (a, 0), vec_extract (b, 0)),
317 		INIT_ORDER (1, 3));
318 
319   vector_check (combine (vec_extract (a, 0), vec_extract (b, 1)),
320 		INIT_ORDER (1, 4));
321 
322   vector_check (combine (vec_extract (a, 1), vec_extract (b, 0)),
323 		INIT_ORDER (2, 3));
324 
325   vector_check (combine (vec_extract (a, 1), vec_extract (b, 1)),
326 		INIT_ORDER (2, 4));
327 
328   vector_check (combine_insert (vec_extract (a, 0), vec_extract (b, 0)),
329 		ELEMENT_ORDER (1, 3));
330 
331   vector_check (combine_insert (vec_extract (a, 0), vec_extract (b, 1)),
332 		ELEMENT_ORDER (1, 4));
333 
334   vector_check (combine_insert (vec_extract (a, 1), vec_extract (b, 0)),
335 		ELEMENT_ORDER (2, 3));
336 
337   vector_check (combine_insert (vec_extract (a, 1), vec_extract (b, 1)),
338 		ELEMENT_ORDER (2, 4));
339 
340 
341 #if defined(DO_DOUBLE)
342   DEBUG0 ("\nTesting explicit 2df concat\n");
343   vector_check (__builtin_vsx_concat_2df (FIVE, SIX), INIT_ORDER (5, 6));
344   vector_check (__builtin_vsx_concat_2df (five, six), INIT_ORDER (5, 6));
345 
346 #elif defined(_ARCH_PPC64)
347   DEBUG0 ("\nTesting explicit 2di concat\n");
348   vector_check (__builtin_vsx_concat_2di (FIVE, SIX), INIT_ORDER (5, 6));
349   vector_check (__builtin_vsx_concat_2di (five, six), INIT_ORDER (5, 6));
350 
351 #else
352   DEBUG0 ("\nSkip explicit 2di concat on 32-bit\n");
353 #endif
354 
355 #ifdef DEBUG
356   if (errors)
357     printf ("\n%d error%s were found", errors, (errors == 1) ? "" : "s");
358   else
359     printf ("\nNo errors were found.\n");
360 
361   return errors;
362 
363 #else
364   return 0;
365 #endif
366 }
367