1ab853107614a94f93c5058b03be61137e956fb27sewardj/*  Copyright (C) 2011 IBM
2
3 Author: Maynard Johnson <maynardj@us.ibm.com>
4
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 License, or (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307, USA.
19
20 The GNU General Public License is contained in the file COPYING.
21 */
22
23#ifdef HAS_VSX
24
25#include <stdio.h>
26#include <stdint.h>
27#include <stdlib.h>
28#include <string.h>
29#include <malloc.h>
30#include <altivec.h>
31#include <math.h>
32
33#ifndef __powerpc64__
34typedef uint32_t HWord_t;
35#else
36typedef uint64_t HWord_t;
37#endif /* __powerpc64__ */
38
39typedef unsigned char Bool;
40#define True 1
41#define False 0
42
43#ifdef VGP_ppc64le_linux
44#define isLE 1
45#else
46#define isLE 0
47#endif
48
49register HWord_t r14 __asm__ ("r14");
50register HWord_t r15 __asm__ ("r15");
51register HWord_t r16 __asm__ ("r16");
52register HWord_t r17 __asm__ ("r17");
53register double f14 __asm__ ("fr14");
54register double f15 __asm__ ("fr15");
55register double f16 __asm__ ("fr16");
56register double f17 __asm__ ("fr17");
57
58static volatile unsigned int div_flags, div_xer;
59
60#define ALLCR "cr0","cr1","cr2","cr3","cr4","cr5","cr6","cr7"
61
62#define SET_CR(_arg) \
63      __asm__ __volatile__ ("mtcr  %0" : : "b"(_arg) : ALLCR );
64
65#define SET_XER(_arg) \
66      __asm__ __volatile__ ("mtxer %0" : : "b"(_arg) : "xer" );
67
68#define GET_CR(_lval) \
69      __asm__ __volatile__ ("mfcr %0"  : "=b"(_lval) )
70
71#define GET_XER(_lval) \
72      __asm__ __volatile__ ("mfxer %0" : "=b"(_lval) )
73
74#define GET_CR_XER(_lval_cr,_lval_xer) \
75   do { GET_CR(_lval_cr); GET_XER(_lval_xer); } while (0)
76
77#define SET_CR_ZERO \
78      SET_CR(0)
79
80#define SET_XER_ZERO \
81      SET_XER(0)
82
83#define SET_CR_XER_ZERO \
84   do { SET_CR_ZERO; SET_XER_ZERO; } while (0)
85
86#define SET_FPSCR_ZERO \
87   do { double _d = 0.0; \
88        __asm__ __volatile__ ("mtfsf 0xFF, %0" : : "f"(_d) ); \
89   } while (0)
90
91
92typedef void (*test_func_t)(void);
93typedef struct test_table test_table_t;
94
95
96/* These functions below that construct a table of floating point
97 * values were lifted from none/tests/ppc32/jm-insns.c.
98 */
99
100#if defined (DEBUG_ARGS_BUILD)
101#define AB_DPRINTF(fmt, args...) do { fprintf(stderr, fmt , ##args); } while (0)
102#else
103#define AB_DPRINTF(fmt, args...) do { } while (0)
104#endif
105
106static inline void register_farg (void *farg,
107                                  int s, uint16_t _exp, uint64_t mant)
108{
109   uint64_t tmp;
110
111   tmp = ((uint64_t)s << 63) | ((uint64_t)_exp << 52) | mant;
112   *(uint64_t *)farg = tmp;
113   AB_DPRINTF("%d %03x %013llx => %016llx %0e\n",
114              s, _exp, mant, *(uint64_t *)farg, *(double *)farg);
115}
116
117static inline void register_sp_farg (void *farg,
118                                     int s, uint16_t _exp, uint32_t mant)
119{
120   uint32_t tmp;
121   tmp = ((uint32_t)s << 31) | ((uint32_t)_exp << 23) | mant;
122   *(uint32_t *)farg = tmp;
123}
124
125typedef struct fp_test_args {
126   int fra_idx;
127   int frb_idx;
128} fp_test_args_t;
129
130
131fp_test_args_t fp_cmp_tests[] = {
132                                   {8, 8},
133                                   {8, 14},
134                                   {8, 6},
135                                   {8, 5},
136                                   {8, 4},
137                                   {8, 7},
138                                   {8, 9},
139                                   {8, 11},
140                                   {14, 8},
141                                   {14, 14},
142                                   {14, 6},
143                                   {14, 5},
144                                   {14, 4},
145                                   {14, 7},
146                                   {14, 9},
147                                   {14, 11},
148                                   {6, 8},
149                                   {6, 14},
150                                   {6, 6},
151                                   {6, 5},
152                                   {6, 4},
153                                   {6, 7},
154                                   {6, 9},
155                                   {6, 11},
156                                   {5, 8},
157                                   {5, 14},
158                                   {5, 6},
159                                   {5, 5},
160                                   {5, 4},
161                                   {5, 7},
162                                   {5, 9},
163                                   {5, 11},
164                                   {4, 8},
165                                   {4, 14},
166                                   {4, 6},
167                                   {4, 5},
168                                   {4, 1},
169                                   {4, 7},
170                                   {4, 9},
171                                   {4, 11},
172                                   {7, 8},
173                                   {7, 14},
174                                   {7, 6},
175                                   {7, 5},
176                                   {7, 4},
177                                   {7, 7},
178                                   {7, 9},
179                                   {7, 11},
180                                   {10, 8},
181                                   {10, 14},
182                                   {10, 6},
183                                   {10, 5},
184                                   {10, 4},
185                                   {10, 7},
186                                   {10, 9},
187                                   {10, 10},
188                                   {12, 8},
189                                   {12, 14},
190                                   {12, 6},
191                                   {12, 5},
192                                   {1, 1},
193                                   {2, 2},
194                                   {3, 3},
195                                   {4, 4},
196};
197
198
199fp_test_args_t two_arg_fp_tests[] = {
200                                     {8, 8},
201                                     {8, 14},
202                                     {15, 16},
203                                     {8, 5},
204                                     {8, 4},
205                                     {8, 7},
206                                     {8, 9},
207                                     {8, 11},
208                                     {14, 8},
209                                     {14, 14},
210                                     {14, 6},
211                                     {14, 5},
212                                     {14, 4},
213                                     {14, 7},
214                                     {14, 9},
215                                     {14, 11},
216                                     {6, 8},
217                                     {6, 14},
218                                     {6, 6},
219                                     {6, 5},
220                                     {6, 4},
221                                     {6, 7},
222                                     {6, 9},
223                                     {6, 11},
224                                     {5, 8},
225                                     {5, 14},
226                                     {5, 6},
227                                     {5, 5},
228                                     {5, 4},
229                                     {5, 7},
230                                     {5, 9},
231                                     {5, 11},
232                                     {4, 8},
233                                     {4, 14},
234                                     {4, 6},
235                                     {4, 5},
236                                     {4, 1},
237                                     {4, 7},
238                                     {4, 9},
239                                     {4, 11},
240                                     {7, 8},
241                                     {7, 14},
242                                     {7, 6},
243                                     {7, 5},
244                                     {7, 4},
245                                     {7, 7},
246                                     {7, 9},
247                                     {7, 11},
248                                     {10, 8},
249                                     {10, 14},
250                                     {12, 6},
251                                     {12, 5},
252                                     {10, 4},
253                                     {10, 7},
254                                     {10, 9},
255                                     {10, 11},
256                                     {12, 8 },
257                                     {12, 14},
258                                     {12, 6},
259                                     {15, 16},
260                                     {15, 16},
261                                     {9, 11},
262                                     {11, 11},
263                                     {11, 12}
264};
265
266
267static int nb_special_fargs;
268static double * spec_fargs;
269static float * spec_sp_fargs;
270
271static void build_special_fargs_table(void)
272{
273/*
274  Entry  Sign Exp   fraction                  Special value
275   0      0   3fd   0x8000000000000ULL         Positive finite number
276   1      0   404   0xf000000000000ULL         ...
277   2      0   001   0x8000000b77501ULL         ...
278   3      0   7fe   0x800000000051bULL         ...
279   4      0   012   0x3214569900000ULL         ...
280   5      0   000   0x0000000000000ULL         +0.0 (+zero)
281   6      1   000   0x0000000000000ULL         -0.0 (-zero)
282   7      0   7ff   0x0000000000000ULL         +infinity
283   8      1   7ff   0x0000000000000ULL         -infinity
284   9      0   7ff   0x7FFFFFFFFFFFFULL         +SNaN
285   10     1   7ff   0x7FFFFFFFFFFFFULL         -SNaN
286   11     0   7ff   0x8000000000000ULL         +QNaN
287   12     1   7ff   0x8000000000000ULL         -QNaN
288   13     1   000   0x8340000078000ULL         Denormalized val (zero exp and non-zero fraction)
289   14     1   40d   0x0650f5a07b353ULL         Negative finite number
290   15     0   412   0x32585a9900000ULL         A couple more positive finite numbers
291   16     0   413   0x82511a2000000ULL         ...
292*/
293
294   uint64_t mant;
295   uint32_t mant_sp;
296   uint16_t _exp;
297   int s;
298   int j, i = 0;
299
300   if (spec_fargs)
301      return;
302
303   spec_fargs = malloc( 17 * sizeof(double) );
304   spec_sp_fargs = malloc( 17 * sizeof(float) );
305
306   // #0
307   s = 0;
308   _exp = 0x3fd;
309   mant = 0x8000000000000ULL;
310   register_farg(&spec_fargs[i++], s, _exp, mant);
311
312   // #1
313   s = 0;
314   _exp = 0x404;
315   mant = 0xf000000000000ULL;
316   register_farg(&spec_fargs[i++], s, _exp, mant);
317
318   /* None of the ftdiv tests succeed.
319    * FRA = value #0; FRB = value #1
320    * ea_ = -2; e_b = 5
321    * fl_flag || fg_flag || fe_flag = 100
322    */
323
324   /*************************************************
325    *     fe_flag tests
326    *
327    *************************************************/
328
329   /* fe_flag <- 1 if FRA is a NaN
330    * FRA = value #9; FRB = value #1
331    * e_a = 1024; e_b = 5
332    * fl_flag || fg_flag || fe_flag = 101
333    */
334
335   /* fe_flag <- 1 if FRB is a NaN
336    * FRA = value #1; FRB = value #12
337    * e_a = 5; e_b = 1024
338    * fl_flag || fg_flag || fe_flag = 101
339    */
340
341   /* fe_flag <- 1 if e_b <= -1022
342    * FRA = value #0; FRB = value #2
343    * e_a = -2; e_b = -1022
344    * fl_flag || fg_flag || fe_flag = 101
345    *
346    */
347   // #2
348   s = 0;
349   _exp = 0x001;
350   mant = 0x8000000b77501ULL;
351   register_farg(&spec_fargs[i++], s, _exp, mant);
352
353   /* fe_flag <- 1 if e_b >= 1021
354    * FRA = value #1; FRB = value #3
355    * e_a = 5; e_b = 1023
356    * fl_flag || fg_flag || fe_flag = 101
357    */
358   // #3
359   s = 0;
360   _exp = 0x7fe;
361   mant = 0x800000000051bULL;
362   register_farg(&spec_fargs[i++], s, _exp, mant);
363
364   /* fe_flag <- 1 if FRA != 0 && e_a - e_b >= 1023
365    * Let FRA = value #3 and FRB be value #0.
366    * e_a = 1023; e_b = -2
367    * fl_flag || fg_flag || fe_flag = 101
368    */
369
370   /* fe_flag <- 1 if FRA != 0 && e_a - e_b <= -1023
371    * Let FRA = value #0 above and FRB be value #3 above
372    * e_a = -2; e_b = 1023
373    * fl_flag || fg_flag || fe_flag = 101
374    */
375
376   /* fe_flag <- 1 if FRA != 0 && e_a <= -970
377    * Let FRA = value #4 and FRB be value #0
378    * e_a = -1005; e_b = -2
379    * fl_flag || fg_flag || fe_flag = 101
380   */
381   // #4
382   s = 0;
383   _exp = 0x012;
384   mant = 0x3214569900000ULL;
385   register_farg(&spec_fargs[i++], s, _exp, mant);
386
387   /*************************************************
388    *     fg_flag tests
389    *
390    *************************************************/
391   /* fg_flag <- 1 if FRA is an Infinity
392    * NOTE: FRA = Inf also sets fe_flag
393    * Do two tests, using values #7 and #8 (+/- Inf) for FRA.
394    * Test 1:
395    *   Let FRA be value #7 and FRB be value #1
396    *   e_a = 1024; e_b = 5
397    *   fl_flag || fg_flag || fe_flag = 111
398    *
399    * Test 2:
400    *   Let FRA be value #8 and FRB be value #1
401    *   e_a = 1024; e_b = 5
402    *   fl_flag || fg_flag || fe_flag = 111
403    *
404    */
405
406   /* fg_flag <- 1 if FRB is an Infinity
407    * NOTE: FRB = Inf also sets fe_flag
408    * Let FRA be value #1 and FRB be value #7
409    * e_a = 5; e_b = 1024
410    * fl_flag || fg_flag || fe_flag = 111
411    */
412
413   /* fg_flag <- 1 if FRB is denormalized
414    * NOTE: e_b < -1022 ==> fe_flag <- 1
415    * Let FRA be value #0 and FRB be value #13
416    * e_a = -2; e_b = -1023
417    * fl_flag || fg_flag || fe_flag = 111
418    */
419
420   /* fg_flag <- 1 if FRB is +zero
421    * NOTE: FRA = Inf also sets fe_flag
422    * Let FRA = val #5; FRB = val #5
423    * ea_ = -1023; e_b = -1023
424    * fl_flag || fg_flag || fe_flag = 111
425    */
426
427   /* fg_flag <- 1 if FRB is -zero
428    * NOTE: FRA = Inf also sets fe_flag
429    * Let FRA = val #5; FRB = val #6
430    * ea_ = -1023; e_b = -1023
431    * fl_flag || fg_flag || fe_flag = 111
432    */
433
434   /* Special values */
435   /* +0.0      : 0 0x000 0x0000000000000 */
436   // #5
437   s = 0;
438   _exp = 0x000;
439   mant = 0x0000000000000ULL;
440   register_farg(&spec_fargs[i++], s, _exp, mant);
441
442   /* -0.0      : 1 0x000 0x0000000000000 */
443   // #6
444   s = 1;
445   _exp = 0x000;
446   mant = 0x0000000000000ULL;
447   register_farg(&spec_fargs[i++], s, _exp, mant);
448
449   /* +infinity : 0 0x7FF 0x0000000000000  */
450   // #7
451   s = 0;
452   _exp = 0x7FF;
453   mant = 0x0000000000000ULL;
454   register_farg(&spec_fargs[i++], s, _exp, mant);
455
456   /* -infinity : 1 0x7FF 0x0000000000000 */
457   // #8
458   s = 1;
459   _exp = 0x7FF;
460   mant = 0x0000000000000ULL;
461   register_farg(&spec_fargs[i++], s, _exp, mant);
462
463   /*
464    * This comment applies to values #9 and #10 below:
465    * When src is a SNaN, it's converted to a QNaN first before rounding to single-precision,
466    * so we can't just copy the double-precision value to the corresponding slot in the
467    * single-precision array (i.e., in the loop at the end of this function).  Instead, we
468    * have to manually set the bits using register_sp_farg().
469    */
470
471   /* +SNaN     : 0 0x7FF 0x7FFFFFFFFFFFF */
472   // #9
473   s = 0;
474   _exp = 0x7FF;
475   mant = 0x7FFFFFFFFFFFFULL;
476   register_farg(&spec_fargs[i++], s, _exp, mant);
477   _exp = 0xff;
478   mant_sp = 0x3FFFFF;
479   register_sp_farg(&spec_sp_fargs[i-1], s, _exp, mant_sp);
480
481   /* -SNaN     : 1 0x7FF 0x7FFFFFFFFFFFF */
482   // #10
483   s = 1;
484   _exp = 0x7FF;
485   mant = 0x7FFFFFFFFFFFFULL;
486   register_farg(&spec_fargs[i++], s, _exp, mant);
487   _exp = 0xff;
488   mant_sp = 0x3FFFFF;
489   register_sp_farg(&spec_sp_fargs[i-1], s, _exp, mant_sp);
490
491   /* +QNaN     : 0 0x7FF 0x8000000000000 */
492   // #11
493   s = 0;
494   _exp = 0x7FF;
495   mant = 0x8000000000000ULL;
496   register_farg(&spec_fargs[i++], s, _exp, mant);
497
498   /* -QNaN     : 1 0x7FF 0x8000000000000 */
499   // #12
500   s = 1;
501   _exp = 0x7FF;
502   mant = 0x8000000000000ULL;
503   register_farg(&spec_fargs[i++], s, _exp, mant);
504
505   /* denormalized value */
506   // #13
507   s = 1;
508   _exp = 0x000;
509   mant = 0x8340000078000ULL;
510   register_farg(&spec_fargs[i++], s, _exp, mant);
511
512   /* Negative finite number */
513   // #14
514   s = 1;
515   _exp = 0x40d;
516   mant = 0x0650f5a07b353ULL;
517   register_farg(&spec_fargs[i++], s, _exp, mant);
518
519   /* A couple positive finite numbers ... */
520   // #15
521   s = 0;
522   _exp = 0x412;
523   mant = 0x32585a9900000ULL;
524   register_farg(&spec_fargs[i++], s, _exp, mant);
525
526   // #16
527   s = 0;
528   _exp = 0x413;
529   mant = 0x82511a2000000ULL;
530   register_farg(&spec_fargs[i++], s, _exp, mant);
531
532   nb_special_fargs = i;
533   for (j = 0; j < i; j++) {
534      if (!(j == 9 || j == 10))
535         spec_sp_fargs[j] = spec_fargs[j];
536   }
537}
538
539
540struct test_table
541{
542   test_func_t test_category;
543   char * name;
544};
545
546typedef enum {
547   SINGLE_TEST,
548   DOUBLE_TEST
549} precision_type_t;
550
551typedef enum {
552   VX_SCALAR_FP_NMSUB = 0,
553   // ALL VECTOR-TYPE OPS SHOULD BE ADDED AFTER THIS LINE
554   VX_VECTOR_FP_MULT_AND_OP2 = 10,
555   // and before this line
556   VX_BASIC_CMP = 30,
557   VX_CONV_WORD,
558   VX_DEFAULT
559} vx_fp_test_type;
560
561typedef struct vx_fp_test
562{
563   test_func_t test_func;
564   const char * name;
565   fp_test_args_t * targs;
566   int num_tests;
567   precision_type_t precision;
568   vx_fp_test_type type;
569   const char * op;
570} vx_fp_test_t;
571
572static vector unsigned int vec_out, vec_inA, vec_inB, vec_inC;
573
574static Bool do_dot;
575static void test_xvcmpeqdp(void)
576{
577   if (do_dot)
578      __asm__ __volatile__ ("xvcmpeqdp.          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
579   else
580      __asm__ __volatile__ ("xvcmpeqdp          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
581}
582
583static void test_xvcmpgedp(void)
584{
585   if (do_dot)
586      __asm__ __volatile__ ("xvcmpgedp.          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
587   else
588      __asm__ __volatile__ ("xvcmpgedp          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
589}
590
591static void test_xvcmpgtdp(void)
592{
593   if (do_dot)
594      __asm__ __volatile__ ("xvcmpgtdp.          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
595   else
596      __asm__ __volatile__ ("xvcmpgtdp          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
597}
598
599static void test_xvcmpeqsp(void)
600{
601   if (do_dot)
602      __asm__ __volatile__ ("xvcmpeqsp.          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
603   else
604      __asm__ __volatile__ ("xvcmpeqsp          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
605}
606
607static void test_xvcmpgesp(void)
608{
609   if (do_dot)
610      __asm__ __volatile__ ("xvcmpgesp.          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
611   else
612      __asm__ __volatile__ ("xvcmpgesp          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
613}
614
615static void test_xvcmpgtsp(void)
616{
617   if (do_dot)
618      __asm__ __volatile__ ("xvcmpgtsp.          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
619   else
620      __asm__ __volatile__ ("xvcmpgtsp          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
621}
622
623static Bool do_aXp;
624static Bool do_dp;
625static void test_xsnmsub(void)
626{
627   if (do_aXp)
628      __asm__ __volatile__ ("xsnmsubadp          %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
629   else
630      __asm__ __volatile__ ("xsnmsubmdp          %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
631}
632
633static void test_xvmadd(void)
634{
635   if (do_aXp)
636      if (do_dp)
637         __asm__ __volatile__ ("xvmaddadp          %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
638      else
639         __asm__ __volatile__ ("xvmaddasp          %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
640   else
641      if (do_dp)
642         __asm__ __volatile__ ("xvmaddmdp          %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
643      else
644         __asm__ __volatile__ ("xvmaddmsp          %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
645}
646
647static void test_xvnmadd(void)
648{
649   if (do_aXp)
650      if (do_dp)
651         __asm__ __volatile__ ("xvnmaddadp          %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
652      else
653         __asm__ __volatile__ ("xvnmaddasp          %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
654   else
655      if (do_dp)
656         __asm__ __volatile__ ("xvnmaddmdp          %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
657      else
658         __asm__ __volatile__ ("xvnmaddmsp          %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
659}
660
661static void test_xvnmsub(void)
662{
663   if (do_aXp)
664      if (do_dp)
665         __asm__ __volatile__ ("xvnmsubadp          %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
666      else
667         __asm__ __volatile__ ("xvnmsubasp          %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
668   else
669      if (do_dp)
670         __asm__ __volatile__ ("xvnmsubmdp          %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
671      else
672         __asm__ __volatile__ ("xvnmsubmsp          %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
673}
674
675static void test_xvmsub(void)
676{
677   if (do_aXp)
678      if (do_dp)
679         __asm__ __volatile__ ("xvmsubadp          %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
680      else
681         __asm__ __volatile__ ("xvmsubasp          %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
682   else
683      if (do_dp)
684         __asm__ __volatile__ ("xvmsubmdp          %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
685      else
686         __asm__ __volatile__ ("xvmsubmsp          %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
687}
688
689static void test_xssqrtdp(void)
690{
691   __asm__ __volatile__ ("xssqrtdp   %x0, %x1" : "=wa" (vec_out): "wa" (vec_inB));
692}
693
694static void test_xsrdpim(void)
695{
696   __asm__ __volatile__ ("xsrdpim   %x0, %x1" : "=wa" (vec_out): "wa" (vec_inB));
697}
698
699static void test_xsrdpip(void)
700{
701   __asm__ __volatile__ ("xsrdpip   %x0, %x1" : "=wa" (vec_out): "wa" (vec_inB));
702}
703
704static void test_xstdivdp(void)
705{
706   __asm__ __volatile__ ("xstdivdp   6, %x0, %x1" : : "wa" (vec_inA), "wa" (vec_inB));
707}
708
709static void test_xsmaxdp(void)
710{
711   __asm__ __volatile__ ("xsmaxdp   %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
712}
713
714static void test_xsmindp(void)
715{
716   __asm__ __volatile__ ("xsmindp   %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
717}
718
719static void test_xvadddp(void)
720{
721   __asm__ __volatile__ ("xvadddp          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
722}
723
724static void test_xvaddsp(void)
725{
726   __asm__ __volatile__ ("xvaddsp          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
727}
728
729static void test_xvdivdp(void)
730{
731   __asm__ __volatile__ ("xvdivdp          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
732}
733
734static void test_xvdivsp(void)
735{
736   __asm__ __volatile__ ("xvdivsp          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
737}
738
739static void test_xvmuldp(void)
740{
741   __asm__ __volatile__ ("xvmuldp          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
742}
743
744static void test_xvmulsp(void)
745{
746   __asm__ __volatile__ ("xvmulsp          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
747}
748
749static void test_xvsubdp(void)
750{
751   __asm__ __volatile__ ("xvsubdp          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
752}
753
754static void test_xvmaxdp(void)
755{
756   __asm__ __volatile__ ("xvmaxdp          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
757}
758
759static void test_xvmindp(void)
760{
761   __asm__ __volatile__ ("xvmindp          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
762}
763
764static void test_xvmaxsp(void)
765{
766   __asm__ __volatile__ ("xvmaxsp          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
767}
768
769static void test_xvminsp(void)
770{
771   __asm__ __volatile__ ("xvminsp          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
772}
773
774static void test_xvsubsp(void)
775{
776   __asm__ __volatile__ ("xvsubsp          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
777}
778
779static void test_xvresp(void)
780{
781   __asm__ __volatile__ ("xvresp   %x0, %x1" : "=wa" (vec_out): "wa" (vec_inB));
782}
783
784static void test_xxsel(void)
785{
786   unsigned long long * dst;
787   unsigned long long xa[] =  { 0xa12bc37de56f9708ULL, 0x3894c1fddeadbeefULL};
788   unsigned long long xb[] =  { 0xfedc432124681235ULL, 0xf1e2d3c4e0057708ULL};
789   unsigned long long xc[] =  { 0xffffffff01020304ULL, 0x128934bd00000000ULL};
790
791   memcpy(&vec_inA, xa, 16);
792   memcpy(&vec_inB, xb, 16);
793   memcpy(&vec_inC, xc, 16);
794
795
796   __asm__ __volatile__ ("xxsel   %x0, %x1, %x2, %x3" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB),"wa" (vec_inC));
797   dst = (unsigned long long *) &vec_out;
798   printf("xxsel %016llx,%016llx,%016llx => %016llx\n", xa[0], xb[0], xc[0], *dst);
799   dst++;
800   printf("xxsel %016llx,%016llx,%016llx => %016llx\n", xa[1], xb[1], xc[1], *dst);
801   printf("\n");
802}
803
804static void test_xxspltw(void)
805{
806   int uim;
807   unsigned long long * dst = NULL;
808   unsigned int xb[] =  { 0xfedc4321, 0x24681235, 0xf1e2d3c4, 0xe0057708};
809   int i;
810   void * vecB_ptr = &vec_inB;
811   if (isLE) {
812      for (i = 3; i >=0; i--) {
813         memcpy(vecB_ptr, &xb[i], 4);
814         vecB_ptr+=4;
815      }
816   } else {
817      for (i = 0; i < 4; i++) {
818         memcpy(vecB_ptr, &xb[i], 4);
819         vecB_ptr+=4;
820      }
821   }
822
823   for (uim = 0; uim < 4; uim++) {
824      switch (uim) {
825         case 0:
826            __asm__ __volatile__ ("xxspltw   %x0, %x1, 0" : "=wa" (vec_out): "wa" (vec_inB));
827            break;
828         case 1:
829            __asm__ __volatile__ ("xxspltw   %x0, %x1, 1" : "=wa" (vec_out): "wa" (vec_inB));
830            break;
831         case 2:
832            __asm__ __volatile__ ("xxspltw   %x0, %x1, 2" : "=wa" (vec_out): "wa" (vec_inB));
833            break;
834         case 3:
835            __asm__ __volatile__ ("xxspltw   %x0, %x1, 3" : "=wa" (vec_out): "wa" (vec_inB));
836            break;
837      }
838      dst = (unsigned long long *) &vec_out;
839      printf("xxspltw 0x%08x%08x%08x%08x %d=> 0x%016llx",  xb[0], xb[1],
840             xb[2], xb[3], uim, *dst);
841      dst++;
842      printf("%016llx\n", *dst);
843   }
844   printf("\n");
845}
846
847static void test_xscvdpsxws(void)
848{
849   __asm__ __volatile__ ("xscvdpsxws  %x0, %x1" : "=wa" (vec_out): "wa" (vec_inB));
850}
851
852static void test_xscvdpuxds(void)
853{
854   __asm__ __volatile__ ("xscvdpuxds  %x0, %x1" : "=wa" (vec_out): "wa" (vec_inB));
855}
856
857static void test_xvcpsgndp(void)
858{
859   __asm__ __volatile__  ("xvcpsgndp  %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
860}
861
862static void test_xvcpsgnsp(void)
863{
864   __asm__ __volatile__  ("xvcpsgnsp  %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
865}
866
867static void test_xvcvdpsxws(void)
868{
869   __asm__ __volatile__ ("xvcvdpsxws  %x0, %x1 " : "=wa" (vec_out): "wa" (vec_inB));
870}
871
872static void test_xvcvspsxws(void)
873{
874   __asm__ __volatile__ ("xvcvspsxws  %x0, %x1 " : "=wa" (vec_out): "wa" (vec_inB));
875}
876
877static vx_fp_test_t
878vx_vector_one_fp_arg_tests[] = {
879                                { &test_xvresp, "xvresp", NULL, 16, SINGLE_TEST, VX_BASIC_CMP, "1/x"},
880                                { &test_xvcvdpsxws, "xvcvdpsxws", NULL, 16, DOUBLE_TEST, VX_CONV_WORD, "conv"},
881                                { &test_xvcvspsxws, "xvcvspsxws", NULL, 16, SINGLE_TEST, VX_CONV_WORD, "conv"},
882                                { NULL, NULL, NULL, 0 , 0, 0, NULL}
883};
884
885static vx_fp_test_t
886vx_vector_fp_tests[] = {
887                        { &test_xvcmpeqdp, "xvcmpeqdp", fp_cmp_tests, 64, DOUBLE_TEST, VX_BASIC_CMP, "eq"},
888                        { &test_xvcmpgedp, "xvcmpgedp", fp_cmp_tests, 64, DOUBLE_TEST, VX_BASIC_CMP, "ge"},
889                        { &test_xvcmpgtdp, "xvcmpgtdp", fp_cmp_tests, 64, DOUBLE_TEST, VX_BASIC_CMP, "gt"},
890                        { &test_xvcmpeqsp, "xvcmpeqsp", fp_cmp_tests, 64, SINGLE_TEST, VX_BASIC_CMP, "eq"},
891                        { &test_xvcmpgesp, "xvcmpgesp", fp_cmp_tests, 64, SINGLE_TEST, VX_BASIC_CMP, "ge"},
892                        { &test_xvcmpgtsp, "xvcmpgtsp", fp_cmp_tests, 64, SINGLE_TEST, VX_BASIC_CMP, "gt"},
893                        { &test_xvadddp, "xvadddp", two_arg_fp_tests, 64, DOUBLE_TEST, VX_DEFAULT, "+" },
894                        { &test_xvaddsp, "xvaddsp", two_arg_fp_tests, 64, SINGLE_TEST, VX_DEFAULT, "+" },
895                        { &test_xvdivdp, "xvdivdp", two_arg_fp_tests, 64, DOUBLE_TEST, VX_DEFAULT, "/" },
896                        { &test_xvdivsp, "xvdivsp", two_arg_fp_tests, 64, SINGLE_TEST, VX_DEFAULT, "/" },
897                        { &test_xvmuldp, "xvmuldp", two_arg_fp_tests, 64, DOUBLE_TEST, VX_DEFAULT, "*" },
898                        { &test_xvmulsp, "xvmulsp", two_arg_fp_tests, 64, SINGLE_TEST, VX_DEFAULT, "*" },
899                        { &test_xvsubdp, "xvsubdp", two_arg_fp_tests, 64, DOUBLE_TEST, VX_DEFAULT, "-" },
900                        { &test_xvsubsp, "xvsubsp", two_arg_fp_tests, 64, SINGLE_TEST, VX_DEFAULT, "-" },
901                        { &test_xvmaxdp, "xvmaxdp", two_arg_fp_tests, 64, DOUBLE_TEST, VX_DEFAULT, "@max@" },
902                        { &test_xvmindp, "xvmindp", two_arg_fp_tests, 64, DOUBLE_TEST, VX_DEFAULT, "@min@" },
903                        { &test_xvmaxsp, "xvmaxsp", two_arg_fp_tests, 64, SINGLE_TEST, VX_DEFAULT, "@max@" },
904                        { &test_xvminsp, "xvminsp", two_arg_fp_tests, 64, SINGLE_TEST, VX_DEFAULT, "@min@" },
905                        { &test_xvcpsgndp, "xvcpsgndp", two_arg_fp_tests, 64, DOUBLE_TEST, VX_DEFAULT, "+-cp"},
906                        { &test_xvcpsgnsp, "xvcpsgnsp", two_arg_fp_tests, 64, SINGLE_TEST, VX_DEFAULT, "+-cp"},
907                        { NULL, NULL, NULL, 0 , 0, 0, NULL}
908};
909
910
911static vx_fp_test_t
912vx_aORm_fp_tests[] = {
913                       { &test_xsnmsub, "xsnmsub", two_arg_fp_tests, 64, DOUBLE_TEST, VX_SCALAR_FP_NMSUB, "!*-"},
914                       { &test_xvmadd, "xvmadd", two_arg_fp_tests, 64, DOUBLE_TEST, VX_VECTOR_FP_MULT_AND_OP2, "*+"},
915                       { &test_xvmadd, "xvmadd", two_arg_fp_tests, 64, SINGLE_TEST, VX_VECTOR_FP_MULT_AND_OP2, "*+"},
916                       { &test_xvnmadd, "xvnmadd", two_arg_fp_tests, 64, DOUBLE_TEST, VX_VECTOR_FP_MULT_AND_OP2, "!*+"},
917                       { &test_xvnmadd, "xvnmadd", two_arg_fp_tests, 64, SINGLE_TEST, VX_VECTOR_FP_MULT_AND_OP2, "!*+"},
918                       { &test_xvmsub, "xvmsub", two_arg_fp_tests, 64, DOUBLE_TEST, VX_VECTOR_FP_MULT_AND_OP2, "*-"},
919                       { &test_xvmsub, "xvmsub", two_arg_fp_tests, 64, SINGLE_TEST, VX_VECTOR_FP_MULT_AND_OP2, "*-"},
920                       { &test_xvnmsub, "xvnmsub", two_arg_fp_tests, 64, DOUBLE_TEST, VX_VECTOR_FP_MULT_AND_OP2, "!*-"},
921                       { &test_xvnmsub, "xvnmsub", two_arg_fp_tests, 64, SINGLE_TEST, VX_VECTOR_FP_MULT_AND_OP2, "!*-"},
922                       { NULL, NULL, NULL, 0, 0, 0,  NULL }
923};
924
925static vx_fp_test_t
926vx_simple_scalar_fp_tests[] = {
927                               { &test_xssqrtdp, "xssqrtdp", NULL, 17, DOUBLE_TEST, VX_DEFAULT, NULL},
928                               { &test_xsrdpim, "xsrdpim", NULL, 17, DOUBLE_TEST, VX_DEFAULT, NULL},
929                               { &test_xsrdpip, "xsrdpip", NULL, 17, DOUBLE_TEST, VX_DEFAULT, NULL},
930                               { &test_xstdivdp, "xstdivdp", two_arg_fp_tests, 64, DOUBLE_TEST, VX_DEFAULT, NULL},
931                               { &test_xsmaxdp, "xsmaxdp", two_arg_fp_tests, 64, DOUBLE_TEST, VX_DEFAULT, NULL},
932                               { &test_xsmindp, "xsmindp", two_arg_fp_tests, 64, DOUBLE_TEST, VX_DEFAULT, NULL},
933                               { &test_xscvdpsxws, "xscvdpsxws", NULL, 17, DOUBLE_TEST, VX_CONV_WORD, NULL},
934                               { &test_xscvdpuxds, "xscvdpuxds", NULL, 17, DOUBLE_TEST, VX_DEFAULT, NULL},
935                               { NULL, NULL, NULL, 0, 0, 0, NULL }
936};
937
938
939#ifdef __powerpc64__
940static void test_bpermd(void)
941{
942   /* NOTE: Bit number is '0 . . . 63'
943    *
944    * Permuted bits are generated bit 0 -7 as follows:
945    *    index = (r14)8*i:8*i+7
946    *    perm[i] = (r15)index
947    *
948    * So, for i = 0, index is (r14)8*0:8*0+7, or (r14)0:7, which is the MSB
949    * byte of r14, 0x1b(27/base 10).  This identifies bit 27 of r15, which is '1'.
950    * For i = 1, index is 0x2c, identifying bit 44 of r15, which is '1'.
951    * So the result of the first two iterations of i are:
952    *   perm = 0b01xxxxxx
953    *
954    */
955   r15 = 0xa12bc37de56f9708ULL;
956   r14 = 0x1b2c31f030000001ULL;
957   __asm__ __volatile__ ("bpermd %0, %1, %2" : "=r" (r17) : "r" (r14),"r" (r15));
958   printf("bpermd: 0x%016llx : 0x%016llx => 0x%llx\n", (unsigned long long)r14,
959          (unsigned long long)r15, (unsigned long long)r17);
960   printf("\n");
961}
962#endif
963
964static Bool do_OE;
965typedef enum {
966   DIV_BASE = 1,
967   DIV_OE = 2,
968   DIV_DOT = 4,
969} div_type_t;
970/* Possible divde type combinations are:
971 *   - base
972 *   - base+dot
973 *   - base+OE
974 *   - base+OE+dot
975 */
976#ifdef __powerpc64__
977static void test_divde(void)
978{
979   int divde_type = DIV_BASE;
980   if (do_OE)
981      divde_type |= DIV_OE;
982   if (do_dot)
983      divde_type |= DIV_DOT;
984
985   switch (divde_type) {
986      case 1:
987        SET_CR_XER_ZERO;
988         __asm__ __volatile__ ("divde %0, %1, %2" : "=r" (r17) : "r" (r14),"r" (r15));
989         GET_CR_XER(div_flags, div_xer);
990         break;
991      case 3:
992        SET_CR_XER_ZERO;
993         __asm__ __volatile__ ("divdeo %0, %1, %2" : "=r" (r17) : "r" (r14),"r" (r15));
994         GET_CR_XER(div_flags, div_xer);
995         break;
996      case 5:
997        SET_CR_XER_ZERO;
998         __asm__ __volatile__ ("divde. %0, %1, %2" : "=r" (r17) : "r" (r14),"r" (r15));
999         GET_CR_XER(div_flags, div_xer);
1000         break;
1001      case 7:
1002        SET_CR_XER_ZERO;
1003         __asm__ __volatile__ ("divdeo. %0, %1, %2" : "=r" (r17) : "r" (r14),"r" (r15));
1004         GET_CR_XER(div_flags, div_xer);
1005         break;
1006      default:
1007         fprintf(stderr, "Invalid divde type. Exiting\n");
1008         exit(1);
1009   }
1010}
1011#endif
1012
1013static void test_divweu(void)
1014{
1015   int divweu_type = DIV_BASE;
1016   if (do_OE)
1017      divweu_type |= DIV_OE;
1018   if (do_dot)
1019      divweu_type |= DIV_DOT;
1020
1021   switch (divweu_type) {
1022      case 1:
1023        SET_CR_XER_ZERO;
1024         __asm__ __volatile__ ("divweu %0, %1, %2" : "=r" (r17) : "r" (r14),"r" (r15));
1025         GET_CR_XER(div_flags, div_xer);
1026         break;
1027      case 3:
1028        SET_CR_XER_ZERO;
1029         __asm__ __volatile__ ("divweuo %0, %1, %2" : "=r" (r17) : "r" (r14),"r" (r15));
1030         GET_CR_XER(div_flags, div_xer);
1031         break;
1032      case 5:
1033        SET_CR_XER_ZERO;
1034         __asm__ __volatile__ ("divweu. %0, %1, %2" : "=r" (r17) : "r" (r14),"r" (r15));
1035         GET_CR_XER(div_flags, div_xer);
1036         break;
1037      case 7:
1038        SET_CR_XER_ZERO;
1039         __asm__ __volatile__ ("divweuo. %0, %1, %2" : "=r" (r17) : "r" (r14),"r" (r15));
1040         GET_CR_XER(div_flags, div_xer);
1041         break;
1042      default:
1043         fprintf(stderr, "Invalid divweu type. Exiting\n");
1044         exit(1);
1045   }
1046}
1047
1048static void test_fctiduz(void)
1049{
1050   if (do_dot)
1051      __asm__ __volatile__ ("fctiduz. %0, %1" : "=d" (f17) : "d" (f14));
1052   else
1053      __asm__ __volatile__ ("fctiduz %0, %1" : "=d" (f17) : "d" (f14));
1054}
1055
1056static void test_fctidu(void)
1057{
1058   if (do_dot)
1059      __asm__ __volatile__ ("fctidu. %0, %1" : "=d" (f17) : "d" (f14));
1060   else
1061      __asm__ __volatile__ ("fctidu %0, %1" : "=d" (f17) : "d" (f14));
1062}
1063
1064static void test_fctiwuz(void)
1065{
1066   if (do_dot)
1067      __asm__ __volatile__ ("fctiwuz. %0, %1" : "=d" (f17) : "d" (f14));
1068   else
1069      __asm__ __volatile__ ("fctiwuz %0, %1" : "=d" (f17) : "d" (f14));
1070}
1071
1072static void test_fctiwu(void)
1073{
1074   if (do_dot)
1075      __asm__ __volatile__ ("fctiwu. %0, %1" : "=d" (f17) : "d" (f14));
1076   else
1077      __asm__ __volatile__ ("fctiwu %0, %1" : "=d" (f17) : "d" (f14));
1078}
1079
1080typedef struct simple_test {
1081   test_func_t test_func;
1082   char * name;
1083   precision_type_t precision;
1084} simple_test_t;
1085
1086static simple_test_t fct_tests[] = {
1087                                    { &test_fctiduz, "fctiduz", DOUBLE_TEST },
1088                                    { &test_fctidu, "fctidu", DOUBLE_TEST },
1089                                    { &test_fctiwuz, "fctiwuz", SINGLE_TEST },
1090                                    { &test_fctiwu, "fctiwu", SINGLE_TEST },
1091                                   { NULL, NULL }
1092};
1093
1094static void setup_sp_fp_args(fp_test_args_t * targs, Bool swap_inputs)
1095{
1096   int a_idx, b_idx, i;
1097   void * inA, * inB;
1098   void * vec_src = swap_inputs ? &vec_out : &vec_inB;
1099
1100   for (i = 0; i < 4; i++) {
1101      a_idx = targs->fra_idx;
1102      b_idx = targs->frb_idx;
1103      inA = (void *)&spec_sp_fargs[a_idx];
1104      inB = (void *)&spec_sp_fargs[b_idx];
1105      // copy single precision FP  into vector element i
1106      memcpy(((void *)&vec_inA) + (i * 4), inA, 4);
1107      memcpy(vec_src + (i * 4), inB, 4);
1108      targs++;
1109   }
1110}
1111
1112static void setup_dp_fp_args(fp_test_args_t * targs, Bool swap_inputs)
1113{
1114   int a_idx, b_idx, i;
1115   void * inA, * inB;
1116   void * vec_src = swap_inputs ? (void *)&vec_out : (void *)&vec_inB;
1117
1118   for (i = 0; i < 2; i++) {
1119      a_idx = targs->fra_idx;
1120      b_idx = targs->frb_idx;
1121      inA = (void *)&spec_fargs[a_idx];
1122      inB = (void *)&spec_fargs[b_idx];
1123      // copy double precision FP  into vector element i
1124      memcpy(((void *)&vec_inA) + (i * 8), inA, 8);
1125      memcpy(vec_src + (i * 8), inB, 8);
1126      targs++;
1127   }
1128}
1129
1130#define VX_NOT_CMP_OP 0xffffffff
1131static void print_vector_fp_result(unsigned int cc, vx_fp_test_t * test_group, int i)
1132{
1133   int a_idx, b_idx, k;
1134   char * name = malloc(20);
1135   int dp = test_group->precision == DOUBLE_TEST ? 1 : 0;
1136   int loops = dp ? 2 : 4;
1137   fp_test_args_t * targs = &test_group->targs[i];
1138   unsigned long long * frA_dp, * frB_dp, * dst_dp;
1139   unsigned int * frA_sp, *frB_sp, * dst_sp;
1140   strcpy(name, test_group->name);
1141   printf("#%d: %s%s ", dp? i/2 : i/4, name, (do_dot ? "." : ""));
1142   for (k = 0; k < loops; k++) {
1143      a_idx = targs->fra_idx;
1144      b_idx = targs->frb_idx;
1145      if (k)
1146         printf(" AND ");
1147      if (dp) {
1148         frA_dp = (unsigned long long *)&spec_fargs[a_idx];
1149         frB_dp = (unsigned long long *)&spec_fargs[b_idx];
1150         printf("%016llx %s %016llx", *frA_dp, test_group->op, *frB_dp);
1151      } else {
1152         frA_sp = (unsigned int *)&spec_sp_fargs[a_idx];
1153         frB_sp = (unsigned int *)&spec_sp_fargs[b_idx];
1154         printf("%08x %s %08x", *frA_sp, test_group->op, *frB_sp);
1155      }
1156      targs++;
1157   }
1158   if (cc != VX_NOT_CMP_OP)
1159      printf(" ? cc=%x", cc);
1160
1161   if (dp) {
1162      dst_dp = (unsigned long long *) &vec_out;
1163      printf(" => %016llx %016llx\n", dst_dp[0], dst_dp[1]);
1164   } else {
1165      dst_sp = (unsigned int *) &vec_out;
1166      printf(" => %08x %08x %08x %08x\n", dst_sp[0], dst_sp[1], dst_sp[2], dst_sp[3]);
1167   }
1168   free(name);
1169}
1170
1171
1172static void print_vx_aORm_fp_result(unsigned long long * XT_arg, unsigned long long * XB_arg,
1173                                    vx_fp_test_t * test_group, int i)
1174{
1175   int a_idx, k;
1176   char * name = malloc(20);
1177   int dp = test_group->precision == DOUBLE_TEST ? 1 : 0;
1178   int loops = dp ? 2 : 4;
1179   fp_test_args_t * targs = &test_group->targs[i];
1180   unsigned long long frA_dp, * dst_dp;
1181   unsigned int frA_sp, * dst_sp;
1182
1183   strcpy(name, test_group->name);
1184   if (do_aXp)
1185      if (dp)
1186         strcat(name, "adp");
1187      else
1188         strcat(name, "asp");
1189   else
1190      if (dp)
1191         strcat(name, "mdp");
1192      else
1193         strcat(name, "msp");
1194
1195   printf("#%d: %s ", dp? i/2 : i/4, name);
1196   for (k = 0; k < loops; k++) {
1197      a_idx = targs->fra_idx;
1198      if (k)
1199         printf(" AND ");
1200      if (dp) {
1201         frA_dp = *((unsigned long long *)&spec_fargs[a_idx]);
1202         printf("%s(%016llx,%016llx,%016llx)", test_group->op, XT_arg[k], frA_dp, XB_arg[k]);
1203      } else {
1204         unsigned int * xt_sp = (unsigned int *)XT_arg;
1205         unsigned int * xb_sp = (unsigned int *)XB_arg;
1206         frA_sp = *((unsigned int *)&spec_sp_fargs[a_idx]);
1207         printf("%s(%08x,%08x,%08x)", test_group->op, xt_sp[k], frA_sp, xb_sp[k]);
1208      }
1209      targs++;
1210   }
1211
1212   if (dp) {
1213      dst_dp = (unsigned long long *) &vec_out;
1214      printf(" => %016llx %016llx\n", dst_dp[0], dst_dp[1]);
1215   } else {
1216      dst_sp = (unsigned int *) &vec_out;
1217      printf(" => %08x %08x %08x %08x\n", dst_sp[0], dst_sp[1], dst_sp[2], dst_sp[3]);
1218   }
1219   free(name);
1220}
1221
1222/* This function currently only supports double precision input arguments. */
1223static void test_vx_simple_scalar_fp_ops(void)
1224{
1225   test_func_t func;
1226   int k = 0;
1227
1228   build_special_fargs_table();
1229   while ((func = vx_simple_scalar_fp_tests[k].test_func)) {
1230      unsigned long long * frap, * frbp, * dst;
1231      unsigned int * pv;
1232      int idx;
1233      vx_fp_test_t test_group = vx_simple_scalar_fp_tests[k];
1234      Bool convToWord = (test_group.type == VX_CONV_WORD);
1235      if (test_group.precision != DOUBLE_TEST) {
1236         fprintf(stderr, "Unsupported single precision for scalar op in test_vx_aORm_fp_ops\n");
1237         exit(1);
1238      }
1239      pv = (unsigned int *)&vec_out;
1240      // clear vec_out
1241      for (idx = 0; idx < 4; idx++, pv++)
1242         *pv = 0;
1243
1244      /* If num_tests is exactly equal to nb_special_fargs, this implies the
1245       * instruction being tested only requires one floating point argument
1246       * (e.g. xssqrtdp).
1247       */
1248      if (test_group.num_tests == nb_special_fargs && !test_group.targs) {
1249         void * inB, * vec_void_ptr = (void *)&vec_inB;
1250         int i;
1251         if (isLE)
1252            vec_void_ptr += 8;
1253         for (i = 0; i < nb_special_fargs; i++) {
1254            inB = (void *)&spec_fargs[i];
1255            frbp = (unsigned long long *)&spec_fargs[i];
1256            memcpy(vec_void_ptr, inB, 8);
1257            (*func)();
1258            dst = (unsigned long long *) &vec_out;
1259            if (isLE)
1260               dst++;
1261            printf("#%d: %s %016llx => %016llx\n", i, test_group.name, *frbp,
1262                   convToWord ? (*dst & 0x00000000ffffffffULL) : *dst);
1263         }
1264      } else {
1265         void * inA, * inB, * vecA_void_ptr, * vecB_void_ptr;
1266         unsigned int condreg, flags;
1267         int isTdiv = (strstr(test_group.name, "xstdivdp") != NULL) ? 1 : 0;
1268         int i;
1269         if (isLE) {
1270            vecA_void_ptr = (void *)&vec_inA + 8;
1271            vecB_void_ptr = (void *)&vec_inB + 8;
1272         } else {
1273            vecA_void_ptr = (void *)&vec_inA;
1274            vecB_void_ptr = (void *)&vec_inB;
1275         }
1276         for (i = 0; i < test_group.num_tests; i++) {
1277            fp_test_args_t aTest = test_group.targs[i];
1278            inA = (void *)&spec_fargs[aTest.fra_idx];
1279            inB = (void *)&spec_fargs[aTest.frb_idx];
1280            frap = (unsigned long long *)&spec_fargs[aTest.fra_idx];
1281            frbp = (unsigned long long *)&spec_fargs[aTest.frb_idx];
1282            // Only need to copy one doubleword into each vector's element 0
1283            memcpy(vecA_void_ptr, inA, 8);
1284            memcpy(vecB_void_ptr, inB, 8);
1285            SET_FPSCR_ZERO;
1286            SET_CR_XER_ZERO;
1287            (*func)();
1288            GET_CR(flags);
1289            if (isTdiv) {
1290               condreg = (flags & 0x000000f0) >> 4;
1291               printf("#%d: %s %016llx,%016llx => cr %x\n", i, test_group.name, *frap, *frbp, condreg);
1292            } else {
1293               dst = (unsigned long long *) &vec_out;
1294               if (isLE)
1295                  dst++;
1296               printf("#%d: %s %016llx,%016llx => %016llx\n", i, test_group.name,
1297                      *frap, *frbp, *dst);
1298            }
1299         }
1300      }
1301      printf( "\n" );
1302      k++;
1303   }
1304}
1305
1306static void test_vx_aORm_fp_ops(void)
1307{
1308   /* These ops need a third src argument, which is stored in element 0 of
1309    * VSX[XT] -- i.e., vec_out.  For the xs<ZZZ>m{d|s}p cases, VSX[XT] holds
1310    * src3 and VSX[XB] holds src2; for the xs<ZZZ>a{d|s}p cases, VSX[XT] holds
1311    * src2 and VSX[XB] holds src3.  The fp_test_args_t that holds the test
1312    * data (input args, result) contain only two inputs, so I arbitrarily
1313    * choose some spec_fargs elements for the third source argument.
1314    * Note that that by using the same input data for a given pair of
1315    * a{d|s}p/m{d|s}p-type instructions (by swapping the src2 and src3
1316    * arguments), the expected result should be the same.
1317    */
1318
1319   test_func_t func;
1320   int k;
1321   char * test_name = (char *)malloc(20);
1322   k = 0;
1323   do_dot = False;
1324
1325   build_special_fargs_table();
1326   while ((func = vx_aORm_fp_tests[k].test_func)) {
1327      int i, stride;
1328      Bool repeat = False;
1329      Bool scalar = False;
1330      unsigned long long * frap, * frbp, * dst;
1331      vx_fp_test_t test_group = vx_aORm_fp_tests[k];
1332      vx_fp_test_type test_type = test_group.type;
1333      do_dp = test_group.precision == DOUBLE_TEST ? True : False;
1334      frap = frbp = NULL;
1335
1336      if (test_type < VX_VECTOR_FP_MULT_AND_OP2) {
1337            scalar = True;
1338            strcpy(test_name, test_group.name);
1339            if (!repeat) {
1340               repeat = 1;
1341               stride = 1;
1342               // Only support double precision scalar ops in this function
1343               if (do_dp) {
1344                  strcat(test_name, "adp");
1345               } else {
1346                  fprintf(stderr, "Unsupported single precision for scalar op in test_vx_aORm_fp_ops\n");
1347                  exit(1);
1348               }
1349               do_aXp = True;
1350            }
1351      } else if (test_type < VX_BASIC_CMP) {
1352         // Then it must be a VX_VECTOR_xxx type
1353            stride = do_dp ? 2 : 4;
1354            if (!repeat) {
1355               // No need to work up the testcase name here, since that will be done in
1356               // the print_vx_aORm_fp_result() function we'll call for vector-type ops.
1357               repeat = 1;
1358               do_aXp = True;
1359            }
1360      } else {
1361            printf("ERROR:  Invalid VX FP test type %d\n", test_type);
1362            exit(1);
1363      }
1364
1365again:
1366      for (i = 0; i < test_group.num_tests; i+=stride) {
1367         void  * inA, * inB;
1368         int m, fp_idx[4];
1369         unsigned long long vsr_XT[2];
1370         unsigned long long vsr_XB[2];
1371         fp_test_args_t aTest = test_group.targs[i];
1372         for (m = 0; m < stride; m++)
1373            fp_idx[m] = i % (nb_special_fargs - stride) + m;
1374
1375         /* When repeat == True, we're on the first time through of one of the VX_FP_SMx
1376          * test types, meaning we're testing a xs<ZZZ>adp case, thus we have to swap
1377          * inputs as described above:
1378          *    src2 <= VSX[XT]
1379          *    src3 <= VSX[XB]
1380          */
1381         if (scalar) {
1382#ifdef VGP_ppc64le_linux
1383#define VECTOR_ADDR(_v) ((void *)&_v) + 8
1384#else
1385#define VECTOR_ADDR(_v) ((void *)&_v)
1386#endif
1387            // For scalar op, only need to copy one doubleword into each vector's element 0
1388            inA = (void *)&spec_fargs[aTest.fra_idx];
1389            inB = (void *)&spec_fargs[aTest.frb_idx];
1390            frap = (unsigned long long *)&spec_fargs[aTest.fra_idx];
1391            memcpy(VECTOR_ADDR(vec_inA), inA, 8);
1392            if (repeat) {
1393               memcpy(VECTOR_ADDR(vec_out), inB, 8);  // src2
1394               memcpy(VECTOR_ADDR(vec_inB), &spec_fargs[fp_idx[0]], 8);  //src3
1395               frbp = (unsigned long long *)&spec_fargs[fp_idx[0]];
1396            } else {
1397               frbp = (unsigned long long *)&spec_fargs[aTest.frb_idx];
1398               memcpy(VECTOR_ADDR(vec_inB), inB, 8);  // src2
1399               memcpy(VECTOR_ADDR(vec_out), &spec_fargs[fp_idx[0]], 8);  //src3
1400            }
1401            memcpy(vsr_XT, VECTOR_ADDR(vec_out), 8);
1402         } else {
1403            int j, loops = do_dp ? 2 : 4;
1404            size_t len = do_dp ? 8 : 4;
1405            void * vec_src = repeat ? (void *)&vec_inB : (void *)&vec_out;
1406            for (j = 0; j < loops; j++) {
1407               if (do_dp)
1408                  memcpy(vec_src + (j * len), &spec_fargs[fp_idx[j]], len);
1409               else
1410                  memcpy(vec_src + (j * len), &spec_sp_fargs[fp_idx[j]], len);
1411            }
1412            if (do_dp)
1413               setup_dp_fp_args(&test_group.targs[i], repeat);
1414            else
1415               setup_sp_fp_args(&test_group.targs[i], repeat);
1416
1417            memcpy(vsr_XT, &vec_out, 16);
1418            memcpy(vsr_XB, &vec_inB, 16);
1419         }
1420
1421         (*func)();
1422         dst = (unsigned long long *) &vec_out;
1423         if (isLE)
1424            dst++;
1425         if (test_type < VX_VECTOR_FP_MULT_AND_OP2)
1426            printf( "#%d: %s %s(%016llx,%016llx,%016llx) = %016llx\n", i,
1427                    test_name, test_group.op, vsr_XT[0], *frap, *frbp, *dst );
1428         else
1429            print_vx_aORm_fp_result(vsr_XT, vsr_XB, &test_group, i);
1430      }
1431      printf( "\n" );
1432
1433      if (repeat) {
1434         repeat = 0;
1435         if (test_type < VX_VECTOR_FP_MULT_AND_OP2) {
1436               strcpy(test_name, test_group.name);
1437               strcat(test_name, "mdp");
1438         }
1439         do_aXp = False;
1440         goto again;
1441      }
1442      k++;
1443   }
1444   printf( "\n" );
1445   free(test_name);
1446}
1447
1448static void test_vx_vector_one_fp_arg(void)
1449{
1450   test_func_t func;
1451   int k;
1452   k = 0;
1453   build_special_fargs_table();
1454
1455   while ((func = vx_vector_one_fp_arg_tests[k].test_func)) {
1456      int idx, i;
1457      vx_fp_test_t test_group = vx_vector_one_fp_arg_tests[k];
1458      Bool convToWord = (test_group.type == VX_CONV_WORD);
1459      Bool dp = (test_group.precision == DOUBLE_TEST) ? True : False;
1460      Bool xvrespTest = (strstr(test_group.name , "xvresp") != NULL) ? True: False;
1461      int stride = dp ? 2 : 4;
1462
1463      for (i = 0; i < test_group.num_tests; i+=stride) {
1464         unsigned int * pv;
1465         void * inB;
1466
1467         pv = (unsigned int *)&vec_out;
1468         // clear vec_out
1469         for (idx = 0; idx < 4; idx++, pv++)
1470            *pv = 0;
1471
1472         if (dp) {
1473            int j;
1474            unsigned long long * frB_dp, *dst_dp;
1475            for (j = 0; j < 2; j++) {
1476               inB = (void *)&spec_fargs[i + j];
1477               // copy double precision FP into vector element i
1478               memcpy(((void *)&vec_inB) + (j * 8), inB, 8);
1479            }
1480            // execute test insn
1481            (*func)();
1482            dst_dp = (unsigned long long *) &vec_out;
1483            printf("#%d: %s ", i/2, test_group.name);
1484            for (j = 0; j < 2; j++) {
1485               if (j)
1486                  printf("; ");
1487               frB_dp = (unsigned long long *)&spec_fargs[i + j];
1488               printf("%s(%016llx)", test_group.op, *frB_dp);
1489               printf(" = %016llx", convToWord ? (dst_dp[j] & 0x00000000ffffffffULL) : dst_dp[j]);
1490            }
1491            printf("\n");
1492         } else {
1493            int j;
1494            unsigned int * frB_sp, * dst_sp;
1495
1496            for (j = 0; j < 4; j++) {
1497               inB = (void *)&spec_sp_fargs[i + j];
1498               // copy single precision FP into vector element i
1499               memcpy(((void *)&vec_inB) + (j * 4), inB, 4);
1500            }
1501            // execute test insn
1502            (*func)();
1503            dst_sp = (unsigned int *) &vec_out;
1504            // print result
1505            printf("#%d: %s ", i/4, test_group.name);
1506            for (j = 0; j < 4; j++) {
1507               if (j)
1508                  printf("; ");
1509               frB_sp = (unsigned int *)&spec_sp_fargs[i + j];
1510               printf("%s(%08x)", test_group.op, *frB_sp);
1511               if (xvrespTest) {
1512                  float calc_diff = fabs(spec_sp_fargs[i + j]/256);
1513                  float sp_res;
1514                  memcpy(&sp_res, &dst_sp[j], 4);
1515                  float div_result = 1/spec_sp_fargs[i + j];
1516                  float real_diff = fabs(sp_res - div_result);
1517                  printf( " ==> %s",
1518                          ( ( sp_res == div_result )
1519                                   || ( isnan(sp_res) && isnan(div_result) )
1520                                   || ( real_diff <= calc_diff ) ) ? "PASS"
1521                                                                     : "FAIL");
1522               } else {
1523                  printf(" = %08x", dst_sp[j]);
1524               }
1525            }
1526            printf("\n");
1527         }
1528      }
1529      k++;
1530      printf( "\n" );
1531   }
1532
1533}
1534
1535/* This function assumes the instruction being tested requires two args. */
1536static void test_vx_vector_fp_ops(void)
1537{
1538   test_func_t func;
1539   int k;
1540   k = 0;
1541   build_special_fargs_table();
1542
1543   while ((func = vx_vector_fp_tests[k].test_func)) {
1544      int idx, i, repeat = 1;
1545      vx_fp_test_t test_group = vx_vector_fp_tests[k];
1546      int stride = test_group.precision == DOUBLE_TEST ? 2 : 4;
1547      do_dot = False;
1548
1549again:
1550      for (i = 0; i < test_group.num_tests; i+=stride) {
1551         unsigned int * pv, condreg;
1552         unsigned int flags;
1553
1554         pv = (unsigned int *)&vec_out;
1555         if (test_group.precision == DOUBLE_TEST)
1556            setup_dp_fp_args(&test_group.targs[i], False);
1557         else
1558            setup_sp_fp_args(&test_group.targs[i], False);
1559
1560         // clear vec_out
1561         for (idx = 0; idx < 4; idx++, pv++)
1562            *pv = 0;
1563
1564         // execute test insn
1565         SET_FPSCR_ZERO;
1566         SET_CR_XER_ZERO;
1567         (*func)();
1568         GET_CR(flags);
1569         if (test_group.type == VX_BASIC_CMP) {
1570            condreg = (flags & 0x000000f0) >> 4;
1571         } else {
1572            condreg = VX_NOT_CMP_OP;
1573         }
1574         print_vector_fp_result(condreg, &test_group, i);
1575      }
1576      printf("\n");
1577      if (repeat && test_group.type == VX_BASIC_CMP) {
1578         repeat = 0;
1579         do_dot = True;
1580         goto again;
1581      }
1582      k++;
1583      printf( "\n" );
1584   }
1585}
1586
1587
1588// The div doubleword test data
1589signed long long div_dw_tdata[13][2] = {
1590                                       { 4, -4 },
1591                                       { 4, -3 },
1592                                       { 4, 4 },
1593                                       { 4, -5 },
1594                                       { 3, 8 },
1595                                       { 0x8000000000000000ULL, 0xa },
1596                                       { 0x50c, -1 },
1597                                       { 0x50c, -4096 },
1598                                       { 0x1234fedc, 0x8000a873 },
1599                                       { 0xabcd87651234fedcULL, 0xa123b893 },
1600                                       { 0x123456789abdcULL, 0 },
1601                                       { 0, 2 },
1602                                       { 0x77, 0xa3499 }
1603};
1604#define dw_tdata_len (sizeof(div_dw_tdata)/sizeof(signed long long)/2)
1605
1606// The div word test data
1607unsigned int div_w_tdata[6][2] = {
1608                              { 0, 2 },
1609                              { 2, 0 },
1610                              { 0x7abc1234, 0xf0000000 },
1611                              { 0xfabc1234, 5 },
1612                              { 77, 66 },
1613                              { 5, 0xfabc1234 },
1614};
1615#define w_tdata_len (sizeof(div_w_tdata)/sizeof(unsigned int)/2)
1616
1617typedef struct div_ext_test
1618{
1619   test_func_t test_func;
1620   const char *name;
1621   int num_tests;
1622   div_type_t div_type;
1623   precision_type_t precision;
1624} div_ext_test_t;
1625
1626static div_ext_test_t div_tests[] = {
1627#ifdef __powerpc64__
1628                                   { &test_divde, "divde", dw_tdata_len, DIV_BASE, DOUBLE_TEST },
1629                                   { &test_divde, "divdeo", dw_tdata_len, DIV_OE, DOUBLE_TEST },
1630#endif
1631                                   { &test_divweu, "divweu", w_tdata_len, DIV_BASE, SINGLE_TEST },
1632                                   { &test_divweu, "divweuo", w_tdata_len, DIV_OE, SINGLE_TEST },
1633                                   { NULL, NULL, 0, 0, 0 }
1634};
1635
1636static void test_div_extensions(void)
1637{
1638   test_func_t func;
1639   int k;
1640   k = 0;
1641
1642   while ((func = div_tests[k].test_func)) {
1643      int i, repeat = 1;
1644      div_ext_test_t test_group = div_tests[k];
1645      do_dot = False;
1646
1647again:
1648      for (i = 0; i < test_group.num_tests; i++) {
1649         unsigned int condreg;
1650
1651         if (test_group.div_type == DIV_OE)
1652            do_OE = True;
1653         else
1654            do_OE = False;
1655
1656         if (test_group.precision == DOUBLE_TEST) {
1657            r14 = div_dw_tdata[i][0];
1658            r15 = div_dw_tdata[i][1];
1659         } else {
1660            r14 = div_w_tdata[i][0];
1661            r15 = div_w_tdata[i][1];
1662         }
1663         // execute test insn
1664         (*func)();
1665         condreg = (div_flags & 0xf0000000) >> 28;
1666         printf("#%d: %s%s: ", i, test_group.name, do_dot ? "." : "");
1667         if (test_group.precision == DOUBLE_TEST) {
1668            printf("0x%016llx / 0x%016llx = 0x%016llx;",
1669                   div_dw_tdata[i][0], div_dw_tdata[i][1], (signed long long) r17);
1670         } else {
1671            printf("0x%08x / 0x%08x = 0x%08x;",
1672                   div_w_tdata[i][0], div_w_tdata[i][1], (unsigned int) r17);
1673         }
1674         printf(" CR=%x; XER=%x\n", condreg, div_xer);
1675      }
1676      printf("\n");
1677      if (repeat) {
1678         repeat = 0;
1679         do_dot = True;
1680         goto again;
1681      }
1682      k++;
1683      printf( "\n" );
1684   }
1685
1686}
1687
1688static void test_fct_ops(void)
1689{
1690   test_func_t func;
1691   int k;
1692   k = 0;
1693
1694   while ((func = fct_tests[k].test_func)) {
1695      int i, repeat = 1;
1696      simple_test_t test_group = fct_tests[k];
1697      do_dot = False;
1698
1699again:
1700      for (i = 0; i < nb_special_fargs; i++) {
1701         double result;
1702#define SINGLE_MASK 0x00000000FFFFFFFFULL
1703
1704         f14 = spec_fargs[i];
1705         // execute test insn
1706         SET_FPSCR_ZERO;
1707         (*func)();
1708         result = f17;
1709         printf("#%d: %s%s: ", i, test_group.name, do_dot ? "." : "");
1710         printf("0x%016llx (%e) ==> 0x%016llx\n",
1711                *((unsigned long long *)(&spec_fargs[i])), spec_fargs[i],
1712                test_group.precision == SINGLE_TEST ? (SINGLE_MASK &
1713                         *((unsigned long long *)(&result))) :
1714                         *((unsigned long long *)(&result)));
1715      }
1716      printf("\n");
1717      if (repeat) {
1718         repeat = 0;
1719         do_dot = True;
1720         goto again;
1721      }
1722      k++;
1723      printf( "\n" );
1724   }
1725}
1726
1727#ifdef __powerpc64__
1728void test_stdbrx(void)
1729{
1730   unsigned long long store, val = 0xdeadbacf12345678ULL;
1731   printf("stdbrx: 0x%llx ==> ", val);
1732   r17 = (HWord_t)val;
1733   r14 = (HWord_t)&store;
1734   __asm__ __volatile__ ("stdbrx %0, 0, %1" : : "r"(r17), "r"(r14));
1735   printf("0x%llx\n", store);
1736   printf( "\n" );
1737}
1738#endif
1739
1740static test_table_t
1741         all_tests[] =
1742{
1743                    { &test_vx_vector_one_fp_arg,
1744                      "Test VSX vector single arg instructions"},
1745                    { &test_vx_vector_fp_ops,
1746                      "Test VSX floating point compare and basic arithmetic instructions" },
1747#ifdef __powerpc64__
1748                     { &test_bpermd,
1749                       "Test bit permute double"},
1750#endif
1751                     { &test_xxsel,
1752                         "Test xxsel instruction" },
1753                     { &test_xxspltw,
1754                         "Test xxspltw instruction" },
1755                     { &test_div_extensions,
1756                       "Test div extensions" },
1757                     { &test_fct_ops,
1758                       "Test floating point convert [word | doubleword] unsigned, with round toward zero" },
1759#ifdef __powerpc64__
1760                     { &test_stdbrx,
1761                      "Test stdbrx instruction"},
1762#endif
1763                     { &test_vx_aORm_fp_ops,
1764                      "Test floating point arithmetic instructions -- with a{d|s}p or m{d|s}p"},
1765                     { &test_vx_simple_scalar_fp_ops,
1766                      "Test scalar floating point arithmetic instructions"},
1767                     { NULL, NULL }
1768};
1769#endif // HAS_VSX
1770
1771int main(int argc, char *argv[])
1772{
1773#ifdef HAS_VSX
1774
1775   test_table_t aTest;
1776   test_func_t func;
1777   int i = 0;
1778
1779   while ((func = all_tests[i].test_category)) {
1780      aTest = all_tests[i];
1781      printf( "%s\n", aTest.name );
1782      (*func)();
1783      i++;
1784   }
1785   if (spec_fargs)
1786     free(spec_fargs);
1787   if (spec_sp_fargs)
1788     free(spec_sp_fargs);
1789
1790#endif // HAS _VSX
1791
1792   return 0;
1793}
1794