1 /*  Copyright (C) 2013 IBM
2 
3  Authors: Carl Love  <carll@us.ibm.com>
4           Maynard Johnson <maynardj@us.ibm.com>
5 
6  This program is free software; you can redistribute it and/or
7  modify it under the terms of the GNU General Public License as
8  published by the Free Software Foundation; either version 2 of the
9  License, or (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful, but
12  WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program; if not, write to the Free Software
18  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19  02111-1307, USA.
20 
21  The GNU General Public License is contained in the file COPYING.
22 
23  This program is based heavily on the test_isa_2_06_part*.c source files.
24  */
25 
26 #include <stdio.h>
27 
28 #ifdef HAS_ISA_2_07
29 
30 #include <stdint.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <malloc.h>
34 #include <altivec.h>
35 #include <math.h>
36 
37 #ifndef __powerpc64__
38 typedef uint32_t HWord_t;
39 #else
40 typedef uint64_t HWord_t;
41 #endif /* __powerpc64__ */
42 
43 #ifdef VGP_ppc64le_linux
44 #define isLE 1
45 #else
46 #define isLE 0
47 #endif
48 
49 register HWord_t r14 __asm__ ("r14");
50 register HWord_t r15 __asm__ ("r15");
51 register HWord_t r16 __asm__ ("r16");
52 register HWord_t r17 __asm__ ("r17");
53 register double f14 __asm__ ("fr14");
54 register double f15 __asm__ ("fr15");
55 register double f16 __asm__ ("fr16");
56 register double f17 __asm__ ("fr17");
57 
58 static volatile unsigned int cond_reg;
59 
60 #define True  1
61 #define False 0
62 
63 #define ALLCR "cr0","cr1","cr2","cr3","cr4","cr5","cr6","cr7"
64 
65 #define SET_CR(_arg) \
66       __asm__ __volatile__ ("mtcr  %0" : : "b"(_arg) : ALLCR );
67 
68 #define SET_XER(_arg) \
69       __asm__ __volatile__ ("mtxer %0" : : "b"(_arg) : "xer" );
70 
71 #define GET_CR(_lval) \
72       __asm__ __volatile__ ("mfcr %0"  : "=b"(_lval) )
73 
74 #define GET_XER(_lval) \
75       __asm__ __volatile__ ("mfxer %0" : "=b"(_lval) )
76 
77 #define GET_CR_XER(_lval_cr,_lval_xer) \
78    do { GET_CR(_lval_cr); GET_XER(_lval_xer); } while (0)
79 
80 #define SET_CR_ZERO \
81       SET_CR(0)
82 
83 #define SET_XER_ZERO \
84       SET_XER(0)
85 
86 #define SET_CR_XER_ZERO \
87    do { SET_CR_ZERO; SET_XER_ZERO; } while (0)
88 
89 #define SET_FPSCR_ZERO \
90    do { double _d = 0.0; \
91         __asm__ __volatile__ ("mtfsf 0xFF, %0" : : "f"(_d) ); \
92    } while (0)
93 
94 typedef unsigned char Bool;
95 
96 
97 /* These functions below that construct a table of floating point
98  * values were lifted from none/tests/ppc32/jm-insns.c.
99  */
100 
101 #if defined (DEBUG_ARGS_BUILD)
102 #define AB_DPRINTF(fmt, args...) do { fprintf(stderr, fmt , ##args); } while (0)
103 #else
104 #define AB_DPRINTF(fmt, args...) do { } while (0)
105 #endif
106 
register_farg(void * farg,int s,uint16_t _exp,uint64_t mant)107 static inline void register_farg (void *farg,
108                                   int s, uint16_t _exp, uint64_t mant)
109 {
110    uint64_t tmp;
111 
112    tmp = ((uint64_t)s << 63) | ((uint64_t)_exp << 52) | mant;
113    *(uint64_t *)farg = tmp;
114    AB_DPRINTF("%d %03x %013llx => %016llx %0e\n",
115               s, _exp, mant, *(uint64_t *)farg, *(double *)farg);
116 }
117 
register_sp_farg(void * farg,int s,uint16_t _exp,uint32_t mant)118 static inline void register_sp_farg (void *farg,
119                                      int s, uint16_t _exp, uint32_t mant)
120 {
121    uint32_t tmp;
122    tmp = ((uint32_t)s << 31) | ((uint32_t)_exp << 23) | mant;
123    *(uint32_t *)farg = tmp;
124 }
125 
126 
127 typedef struct fp_test_args {
128    int fra_idx;
129    int frb_idx;
130 } fp_test_args_t;
131 
132 static int nb_special_fargs;
133 static double * spec_fargs;
134 static float * spec_sp_fargs;
135 
build_special_fargs_table(void)136 static void build_special_fargs_table(void)
137 {
138    /*
139     * Double precision:
140     * Sign goes from zero to one               (1 bit)
141     * Exponent goes from 0 to ((1 << 12) - 1)  (11 bits)
142     * Mantissa goes from 1 to ((1 << 52) - 1)  (52 bits)
143     * + special values:
144     * +0.0      : 0 0x000 0x0000000000000 => 0x0000000000000000
145     * -0.0      : 1 0x000 0x0000000000000 => 0x8000000000000000
146     * +infinity : 0 0x7FF 0x0000000000000 => 0x7FF0000000000000
147     * -infinity : 1 0x7FF 0x0000000000000 => 0xFFF0000000000000
148     * +SNaN     : 0 0x7FF 0x7FFFFFFFFFFFF => 0x7FF7FFFFFFFFFFFF
149     * -SNaN     : 1 0x7FF 0x7FFFFFFFFFFFF => 0xFFF7FFFFFFFFFFFF
150     * +QNaN     : 0 0x7FF 0x8000000000000 => 0x7FF8000000000000
151     * -QNaN     : 1 0x7FF 0x8000000000000 => 0xFFF8000000000000
152     * (8 values)
153     *
154     * Single precision
155     * Sign:     1 bit
156     * Exponent: 8 bits
157     * Mantissa: 23 bits
158     * +0.0      : 0 0x00 0x000000 => 0x00000000
159     * -0.0      : 1 0x00 0x000000 => 0x80000000
160     * +infinity : 0 0xFF 0x000000 => 0x7F800000
161     * -infinity : 1 0xFF 0x000000 => 0xFF800000
162     * +SNaN     : 0 0xFF 0x3FFFFF => 0x7FBFFFFF
163     * -SNaN     : 1 0xFF 0x3FFFFF => 0xFFBFFFFF
164     * +QNaN     : 0 0xFF 0x400000 => 0x7FC00000
165     * -QNaN     : 1 0xFF 0x400000 => 0xFFC00000
166    */
167 
168    uint64_t mant;
169    uint32_t mant_sp;
170    uint16_t _exp;
171    int s;
172    int j, i = 0;
173 
174    if (spec_fargs)
175       return;
176 
177    spec_fargs = malloc( 20 * sizeof(double) );
178    spec_sp_fargs = malloc( 20 * sizeof(float) );
179 
180    // #0
181    s = 0;
182    _exp = 0x3fd;
183    mant = 0x8000000000000ULL;
184    register_farg(&spec_fargs[i++], s, _exp, mant);
185 
186    // #1
187    s = 0;
188    _exp = 0x404;
189    mant = 0xf000000000000ULL;
190    register_farg(&spec_fargs[i++], s, _exp, mant);
191 
192    // #2
193    s = 0;
194    _exp = 0x001;
195    mant = 0x8000000b77501ULL;
196    register_farg(&spec_fargs[i++], s, _exp, mant);
197 
198    // #3
199    s = 0;
200    _exp = 0x7fe;
201    mant = 0x800000000051bULL;
202    register_farg(&spec_fargs[i++], s, _exp, mant);
203 
204    // #4
205    s = 0;
206    _exp = 0x012;
207    mant = 0x3214569900000ULL;
208    register_farg(&spec_fargs[i++], s, _exp, mant);
209 
210    /* Special values */
211    /* +0.0      : 0 0x000 0x0000000000000 */
212    // #5
213    s = 0;
214    _exp = 0x000;
215    mant = 0x0000000000000ULL;
216    register_farg(&spec_fargs[i++], s, _exp, mant);
217 
218    /* -0.0      : 1 0x000 0x0000000000000 */
219    // #6
220    s = 1;
221    _exp = 0x000;
222    mant = 0x0000000000000ULL;
223    register_farg(&spec_fargs[i++], s, _exp, mant);
224 
225    /* +infinity : 0 0x7FF 0x0000000000000  */
226    // #7
227    s = 0;
228    _exp = 0x7FF;
229    mant = 0x0000000000000ULL;
230    register_farg(&spec_fargs[i++], s, _exp, mant);
231 
232    /* -infinity : 1 0x7FF 0x0000000000000 */
233    // #8
234    s = 1;
235    _exp = 0x7FF;
236    mant = 0x0000000000000ULL;
237    register_farg(&spec_fargs[i++], s, _exp, mant);
238 
239    /*
240     * This comment applies to values #9 and #10 below:
241     * When src is a SNaN, it's converted to a QNaN first before rounding to single-precision,
242     * so we can't just copy the double-precision value to the corresponding slot in the
243     * single-precision array (i.e., in the loop at the end of this function).  Instead, we
244     * have to manually set the bits using register_sp_farg().
245     */
246 
247    /* +SNaN     : 0 0x7FF 0x7FFFFFFFFFFFF */
248    // #9
249    s = 0;
250    _exp = 0x7FF;
251    mant = 0x7FFFFFFFFFFFFULL;
252    register_farg(&spec_fargs[i++], s, _exp, mant);
253    _exp = 0xff;
254    mant_sp = 0x3FFFFF;
255    register_sp_farg(&spec_sp_fargs[i-1], s, _exp, mant_sp);
256 
257    /* -SNaN     : 1 0x7FF 0x7FFFFFFFFFFFF */
258    // #10
259    s = 1;
260    _exp = 0x7FF;
261    mant = 0x7FFFFFFFFFFFFULL;
262    register_farg(&spec_fargs[i++], s, _exp, mant);
263    _exp = 0xff;
264    mant_sp = 0x3FFFFF;
265    register_sp_farg(&spec_sp_fargs[i-1], s, _exp, mant_sp);
266 
267    /* +QNaN     : 0 0x7FF 0x8000000000000 */
268    // #11
269    s = 0;
270    _exp = 0x7FF;
271    mant = 0x8000000000000ULL;
272    register_farg(&spec_fargs[i++], s, _exp, mant);
273 
274    /* -QNaN     : 1 0x7FF 0x8000000000000 */
275    // #12
276    s = 1;
277    _exp = 0x7FF;
278    mant = 0x8000000000000ULL;
279    register_farg(&spec_fargs[i++], s, _exp, mant);
280 
281    /* denormalized value */
282    // #13
283    s = 1;
284    _exp = 0x000;
285    mant = 0x8340000078000ULL;
286    register_farg(&spec_fargs[i++], s, _exp, mant);
287 
288    /* Negative finite number */
289    // #14
290    s = 1;
291    _exp = 0x40d;
292    mant = 0x0650f5a07b353ULL;
293    register_farg(&spec_fargs[i++], s, _exp, mant);
294 
295    /* A few positive finite numbers ... */
296    // #15
297    s = 0;
298    _exp = 0x412;
299    mant = 0x32585a9900000ULL;
300    register_farg(&spec_fargs[i++], s, _exp, mant);
301 
302    // #16
303    s = 0;
304    _exp = 0x413;
305    mant = 0x82511a2000000ULL;
306    register_farg(&spec_fargs[i++], s, _exp, mant);
307 
308    // #17
309    s = 0;
310    _exp = 0x403;
311    mant = 0x12ef5a9300000ULL;
312    register_farg(&spec_fargs[i++], s, _exp, mant);
313 
314    // #18
315    s = 0;
316    _exp = 0x405;
317    mant = 0x14bf5d2300000ULL;
318    register_farg(&spec_fargs[i++], s, _exp, mant);
319 
320    // #19
321    s = 0;
322    _exp = 0x409;
323    mant = 0x76bf982440000ULL;
324    register_farg(&spec_fargs[i++], s, _exp, mant);
325 
326 
327    nb_special_fargs = i;
328    for (j = 0; j < i; j++) {
329       if (!(j == 9 || j == 10))
330          spec_sp_fargs[j] = spec_fargs[j];
331    }
332 }
333 
334 static unsigned int vstg[] __attribute__ ((aligned (16))) = { 0, 0, 0,0,
335                                                               0, 0, 0, 0 };
336 
337 
338 static unsigned int viargs[] __attribute__ ((aligned (16))) = { 0x80000001,
339                                                                 0x89abcdef,
340                                                                 0x00112233,
341                                                                 0x74556677,
342                                                                 0x00001abb,
343                                                                 0x00000001,
344                                                                 0x31929394,
345                                                                 0xa1a2a3a4,
346 };
347 #define NUM_VIARGS_INTS (sizeof viargs/sizeof viargs[0])
348 #define NUM_VIARGS_VECS  (NUM_VIARGS_INTS/4)
349 
350 
351 static unsigned long long vdargs[] __attribute__ ((aligned (16))) = {
352                                                                      0x0102030405060708ULL,
353                                                                      0x090A0B0C0E0D0E0FULL,
354                                                                      0xF1F2F3F4F5F6F7F8ULL,
355                                                                      0xF9FAFBFCFEFDFEFFULL
356 };
357 #define NUM_VDARGS_INTS (sizeof vdargs/sizeof vdargs[0])
358 #define NUM_VDARGS_VECS  (NUM_VDARGS_INTS/2)
359 
360 typedef void (*test_func_t)(void);
361 
362 struct test_table
363 {
364    test_func_t test_category;
365    char * name;
366 };
367 
368 
369 typedef enum {
370    SINGLE_TEST,
371    SINGLE_TEST_SINGLE_RES,
372    DOUBLE_TEST,
373    DOUBLE_TEST_SINGLE_RES
374 } precision_type_t;
375 #define IS_DP_RESULT(x) ((x == SINGLE_TEST) || (x == DOUBLE_TEST))
376 
377 typedef enum {
378    VX_FP_SMAS,   // multiply add single precision result
379    VX_FP_SMSS,   // multiply sub single precision result
380    VX_FP_SNMAS,  // negative multiply add single precision result
381    VX_FP_SNMSS,  // negative multiply sub single precision result
382    VX_FP_OTHER,
383    VX_CONV_WORD,
384    VX_ESTIMATE,
385    VX_CONV_TO_SINGLE,
386    VX_CONV_TO_DOUBLE,
387    VX_SCALAR_CONV_TO_WORD,
388    VX_SCALAR_SP_TO_VECTOR_SP,
389    VX_DEFAULT
390 } vx_fp_test_type;
391 
392 typedef enum {
393    VSX_LOAD = 1,
394    VSX_LOAD_SPLAT,
395    VSX_STORE,
396 } vsx_ldst_type;
397 
398 typedef enum {
399    VSX_AND = 1,
400    VSX_NAND,
401    VSX_ANDC,
402    VSX_OR,
403    VSX_ORC,
404    VSX_NOR,
405    VSX_XOR,
406    VSX_EQV,
407 } vsx_log_op;
408 
409 struct vx_fp_test1
410 {
411    test_func_t test_func;
412    const char *name;
413    fp_test_args_t * targs;
414    int num_tests;
415     vx_fp_test_type test_type;
416  };
417 
418 struct ldst_test
419 {
420    test_func_t test_func;
421    const char *name;
422    precision_type_t precision;
423    void * base_addr;
424    uint32_t offset;
425    vsx_ldst_type type;
426 };
427 
428 struct vx_fp_test2
429 {
430    test_func_t test_func;
431    const char *name;
432    fp_test_args_t * targs;
433    int num_tests;
434    precision_type_t precision;
435    vx_fp_test_type test_type;
436    const char * op;
437 };
438 
439 struct xs_conv_test
440 {
441    test_func_t test_func;
442    const char *name;
443    int num_tests;
444 };
445 
446 struct simple_test
447 {
448    test_func_t test_func;
449    const char *name;
450 };
451 
452 struct vsx_logic_test
453 {
454    test_func_t test_func;
455    const char *name;
456    vsx_log_op op;
457 };
458 
459 typedef struct vsx_logic_test logic_test_t;
460 typedef struct ldst_test ldst_test_t;
461 typedef struct simple_test xs_conv_test_t;
462 typedef struct vx_fp_test1 vx_fp_test_basic_t;
463 typedef struct vx_fp_test2 vx_fp_test2_t;
464 typedef struct test_table test_table_t;
465 
466 
467 static vector unsigned int vec_out, vec_inA, vec_inB;
468 
test_xscvdpspn(void)469 static void test_xscvdpspn(void)
470 {
471    __asm__ __volatile__ ("xscvdpspn   %x0, %x1" : "=wa" (vec_out): "wa" (vec_inB));
472 }
473 
test_xscvspdpn(void)474 static void test_xscvspdpn(void)
475 {
476    __asm__ __volatile__ ("xscvspdpn  %x0, %x1" : "=wa" (vec_out): "wa" (vec_inB));
477 }
478 
479 static int do_asp;
test_xsmadds(void)480 static void test_xsmadds(void)
481 {
482    if (do_asp)
483       __asm__ __volatile__ ("xsmaddasp          %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
484    else
485       __asm__ __volatile__ ("xsmaddmsp          %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
486 }
487 
test_xsmsubs(void)488 static void test_xsmsubs(void)
489 {
490    if (do_asp)
491       __asm__ __volatile__ ("xsmsubasp          %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
492    else
493       __asm__ __volatile__ ("xsmsubmsp          %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
494 }
495 
test_xscvsxdsp(void)496 static void test_xscvsxdsp (void)
497 {
498    __asm__ __volatile__ ("xscvsxdsp          %x0, %x1" : "=wa" (vec_out): "wa" (vec_inB));
499 }
500 
test_xscvuxdsp(void)501 static void test_xscvuxdsp (void)
502 {
503    __asm__ __volatile__ ("xscvuxdsp          %x0, %x1" : "=wa" (vec_out): "wa" (vec_inB));
504 }
505 
test_xsnmadds(void)506 static void test_xsnmadds(void)
507 {
508    if (do_asp)
509       __asm__ __volatile__ ("xsnmaddasp        %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
510    else
511       __asm__ __volatile__ ("xsnmaddmsp        %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
512 }
513 
test_xsnmsubs(void)514 static void test_xsnmsubs(void)
515 {
516    if (do_asp)
517       __asm__ __volatile__ ("xsnmsubasp        %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
518    else
519       __asm__ __volatile__ ("xsnmsubmsp        %x0, %x1, %x2" : "+wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
520 }
521 
test_stxsspx(void)522 static void test_stxsspx(void)
523 {
524    __asm__ __volatile__ ("stxsspx          %x0, %1, %2" : : "wa" (vec_inA), "b" (r14),"r" (r15));
525 }
526 
test_stxsiwx(void)527 static void test_stxsiwx(void)
528 {
529    __asm__ __volatile__ ("stxsiwx          %x0, %1, %2" : : "wa" (vec_inA), "b" (r14),"r" (r15));
530 }
531 
test_lxsiwax(void)532 static void test_lxsiwax(void)
533 {
534    __asm__ __volatile__ ("lxsiwax          %x0, %1, %2" : "=wa" (vec_out): "b" (r14),"r" (r15));
535 }
536 
test_lxsiwzx(void)537 static void test_lxsiwzx(void)
538 {
539    __asm__ __volatile__ ("lxsiwzx          %x0, %1, %2" : "=wa" (vec_out): "b" (r14),"r" (r15));
540 }
541 
test_lxsspx(void)542 static void test_lxsspx(void)
543 {
544    __asm__ __volatile__ ("lxsspx          %x0, %1, %2" : "=wa" (vec_out): "b" (r14),"r" (r15));
545 }
546 
test_xssqrtsp(void)547 static void test_xssqrtsp(void)
548 {
549    __asm__ __volatile__ ("xssqrtsp         %x0, %x1" : "=wa" (vec_out): "wa" (vec_inB));
550 }
551 
test_xsrsqrtesp(void)552 static void test_xsrsqrtesp(void)
553 {
554    __asm__ __volatile__ ("xsrsqrtesp         %x0, %x1" : "=wa" (vec_out): "wa" (vec_inB));
555 }
556 
557 /* Three argument instuctions */
test_xxleqv(void)558 static void test_xxleqv(void)
559 {
560    __asm__ __volatile__ ("xxleqv          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
561 }
562 
test_xxlorc(void)563 static void test_xxlorc(void)
564 {
565    __asm__ __volatile__ ("xxlorc          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
566 }
567 
test_xxlnand(void)568 static void test_xxlnand(void)
569 {
570    __asm__ __volatile__ ("xxlnand         %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
571 }
572 
test_xsaddsp(void)573 static void test_xsaddsp(void)
574 {
575   __asm__ __volatile__ ("xsaddsp   %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA), "wa" (vec_inB));
576 }
577 
test_xssubsp(void)578 static void test_xssubsp(void)
579 {
580   __asm__ __volatile__ ("xssubsp   %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA), "wa" (vec_inB));
581 }
582 
test_xsdivsp(void)583 static void test_xsdivsp(void)
584 {
585   __asm__ __volatile__ ("xsdivsp   %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA), "wa" (vec_inB));
586 }
587 
test_xsmulsp(void)588 static void test_xsmulsp(void)
589 {
590    __asm__ __volatile__ ("xsmulsp          %x0, %x1, %x2" : "=wa" (vec_out): "wa" (vec_inA),"wa" (vec_inB));
591 }
592 
test_xsresp(void)593 static void test_xsresp(void)
594 {
595    __asm__ __volatile__ ("xsresp   %x0, %x1" : "=wa" (vec_out): "wa" (vec_inB));
596 }
test_xsrsp(void)597 static void test_xsrsp(void)
598 {
599    __asm__ __volatile__ ("xsrsp   %x0, %x1" : "=wa" (vec_out): "wa" (vec_inB));
600 }
601 
602 fp_test_args_t vx_math_tests[] = {
603                                   {8, 8},
604                                   {8, 14},
605                                   {8, 6},
606                                   {8, 5},
607                                   {8, 4},
608                                   {8, 7},
609                                   {8, 9},
610                                   {8, 11},
611                                   {14, 8},
612                                   {14, 14},
613                                   {14, 6},
614                                   {14, 5},
615                                   {14, 4},
616                                   {14, 7},
617                                   {14, 9},
618                                   {14, 11},
619                                   {6, 8},
620                                   {6, 14},
621                                   {6, 6},
622                                   {6, 5},
623                                   {6, 4},
624                                   {6, 7},
625                                   {6, 9},
626                                   {6, 11},
627                                   {5, 8},
628                                   {5, 14},
629                                   {5, 6},
630                                   {5, 5},
631                                   {5, 4},
632                                   {5, 7},
633                                   {5, 9},
634                                   {5, 11},
635                                   {4, 8},
636                                   {4, 14},
637                                   {4, 6},
638                                   {4, 5},
639                                   {4, 1},
640                                   {4, 7},
641                                   {4, 9},
642                                   {4, 11},
643                                   {7, 8},
644                                   {7, 14},
645                                   {7, 6},
646                                   {7, 5},
647                                   {7, 4},
648                                   {7, 7},
649                                   {7, 9},
650                                   {7, 11},
651                                   {10, 8},
652                                   {10, 14},
653                                   {10, 6},
654                                   {10, 5},
655                                   {10, 4},
656                                   {10, 7},
657                                   {10, 9},
658                                   {10, 11},
659                                   {12, 8},
660                                   {12, 14},
661                                   {12, 6},
662                                   {12, 5},
663                                   {12, 4},
664                                   {12, 7},
665                                   {12, 9},
666                                   {12, 11},
667                                   {8, 8},
668                                   {8, 14},
669                                   {8, 6},
670                                   {8, 5},
671                                   {8, 4},
672                                   {8, 7},
673                                   {8, 9},
674                                   {8, 11},
675                                   {14, 8},
676                                   {14, 14},
677                                   {14, 6},
678                                   {14, 5},
679                                   {14, 4},
680                                   {14, 7},
681                                   {14, 9},
682                                   {14, 11},
683                                   {6, 8},
684                                   {6, 14},
685                                   {6, 6},
686                                   {6, 5},
687                                   {6, 4},
688                                   {6, 7},
689                                   {6, 9},
690                                   {6, 11},
691                                   {5, 8},
692                                   {5, 14},
693                                   {5, 6},
694                                   {5, 5},
695                                   {5, 4},
696                                   {5, 7},
697                                   {5, 9},
698                                   {5, 11},
699                                   {4, 8},
700                                   {4, 14},
701                                   {4, 6},
702                                   {4, 5},
703                                   {4, 1},
704                                   {4, 7},
705                                   {4, 9},
706                                   {4, 11},
707                                   {7, 8},
708                                   {7, 14},
709                                   {7, 6},
710                                   {7, 5},
711                                   {7, 4},
712                                   {7, 7},
713                                   {7, 9},
714                                   {7, 11},
715                                   {10, 8},
716                                   {10, 14},
717                                   {10, 6},
718                                   {10, 5},
719                                   {10, 4},
720                                   {10, 7},
721                                   {10, 9},
722                                   {10, 11},
723                                   {12, 8},
724                                   {12, 14},
725                                   {12, 6},
726                                   {12, 5},
727                                   {12, 4},
728                                   {12, 7},
729                                   {12, 9},
730                                   {12, 11}
731 };
732 
733 // These are all double precision inputs with double word outputs (mostly converted to single precision)
734 static vx_fp_test_basic_t vx_fp_tests[] = {
735                                      { &test_xsmadds, "xsmadd", vx_math_tests, 64, VX_FP_SMAS},
736                                      { &test_xsmsubs, "xsmsub", vx_math_tests, 64, VX_FP_SMSS},
737                                      { &test_xsmulsp, "xsmulsp", vx_math_tests, 64, VX_FP_OTHER},
738                                      { &test_xsdivsp, "xsdivsp", vx_math_tests, 64, VX_FP_OTHER},
739                                      { &test_xsnmadds, "xsnmadd", vx_math_tests, 64, VX_FP_SNMAS},
740                                      { &test_xsnmsubs, "xsnmsub", vx_math_tests, 64, VX_FP_SNMSS},
741                                      { NULL, NULL, NULL, 0, 0 }
742 };
743 
744 static vx_fp_test2_t
745 vsx_one_fp_arg_tests[] = {
746                           { &test_xscvdpspn, "xscvdpspn", NULL, 20, DOUBLE_TEST_SINGLE_RES, VX_SCALAR_SP_TO_VECTOR_SP, "conv"},
747                           { &test_xscvspdpn, "xscvspdpn", NULL, 20, SINGLE_TEST, VX_DEFAULT, "conv"},
748                           { &test_xsresp,    "xsresp", NULL, 20, DOUBLE_TEST, VX_ESTIMATE, "1/x"},
749                           { &test_xsrsp,     "xsrsp", NULL, 20, DOUBLE_TEST, VX_DEFAULT, "round"},
750                           { &test_xsrsqrtesp, "xsrsqrtesp", NULL, 20, DOUBLE_TEST, VX_ESTIMATE, "1/sqrt"},
751                           { &test_xssqrtsp, "xssqrtsp", NULL, 20, DOUBLE_TEST, VX_DEFAULT, "sqrt"},
752                           { NULL, NULL, NULL, 0, 0, 0, NULL}
753 };
754 
755 // These are all double precision inputs with double word outputs (mostly converted to single precision)
756 static vx_fp_test_basic_t
757 vx_simple_scalar_fp_tests[] = {
758                           { &test_xssubsp, "xssubsp", vx_math_tests, 64, VX_DEFAULT},
759                           { &test_xsaddsp, "xsaddsp", vx_math_tests, 64, VX_DEFAULT},
760                           { NULL, NULL, NULL, 0 , 0}
761 };
762 
763 static ldst_test_t
764 ldst_tests[] = {
765                     { &test_stxsspx, "stxsspx", DOUBLE_TEST_SINGLE_RES, vstg, 0, VSX_STORE },
766                     { &test_stxsiwx, "stxsiwx", SINGLE_TEST_SINGLE_RES, vstg, 4, VSX_STORE },
767                     { &test_lxsiwax, "lxsiwax", SINGLE_TEST, viargs, 0, VSX_LOAD },
768                     { &test_lxsiwzx, "lxsiwzx", SINGLE_TEST, viargs, 4, VSX_LOAD },
769                     { &test_lxsspx,  "lxsspx",  SINGLE_TEST, NULL, 0, VSX_LOAD },
770                     { NULL, NULL, 0, NULL, 0, 0 } };
771 
772 static xs_conv_test_t
773 xs_conv_tests[] = {
774                    { &test_xscvsxdsp, "xscvsxdsp"},
775                    { &test_xscvuxdsp, "xscvuxdsp"},
776                    { NULL, NULL}
777 };
778 
779 static logic_test_t
780 logic_tests[] = {
781                  { &test_xxleqv,  "xxleqv", VSX_EQV },
782                  { &test_xxlorc,  "xxlorc", VSX_ORC },
783                  { &test_xxlnand, "xxlnand", VSX_NAND },
784                  { NULL, NULL}
785 };
786 
check_reciprocal_estimate(Bool is_rsqrte,int idx,int output_vec_idx)787 Bool check_reciprocal_estimate(Bool is_rsqrte, int idx, int output_vec_idx)
788 {
789    /* NOTE:
790     * This function has been verified only with the xsresp and xsrsqrtes instructions.
791     *
792     * Technically, the number of bits of precision for xsresp and xsrsqrtesp is
793     * 14 bits (14 = log2 16384).  However, the VEX emulation of these instructions
794     * does an actual reciprocal calculation versus estimation, so the answer we get back from
795     * valgrind can easily differ from the estimate in the lower bits (within the 14 bits of
796     * precision) and the estimate may still be within expected tolerances.  On top of that,
797     * we can't count on these estimates always being the same across implementations.
798     * For example, with the fre[s] instruction (which should be correct to within one part
799     * in 256 -- i.e., 8 bits of precision) . . . When approximating the value 1.0111_1111_1111,
800     * one implementation could return 1.0111_1111_0000 and another implementation could return
801     * 1.1000_0000_0000.  Both estimates meet the 1/256 accuracy requirement, but share only a
802     * single bit in common.
803     *
804     * The upshot is we can't validate the VEX output for these instructions by comparing against
805     * stored bit patterns.  We must check that the result is within expected tolerances.
806     */
807 
808    /* A mask to be used for validation as a last resort.
809     * Only use 12 bits of precision for reasons discussed above.
810     */
811 #define VSX_RECIP_ESTIMATE_MASK_SP 0xFFFF8000
812 
813 
814    Bool result = False;
815    double src_dp, res_dp;
816    float calc_diff = 0;
817    float real_diff = 0;
818    double recip_divisor;
819    float div_result;
820    float calc_diff_tmp;
821 
822    src_dp = res_dp = 0;
823    Bool src_is_negative = False;
824    Bool res_is_negative = False;
825    unsigned long long * dst_dp = NULL;
826    unsigned long long * src_dp_ull;
827    dst_dp = (unsigned long long *) &vec_out;
828    src_dp = spec_fargs[idx];
829    src_dp_ull = (unsigned long long *) &src_dp;
830    src_is_negative = (*src_dp_ull & 0x8000000000000000ULL) ? True : False;
831    res_is_negative = (dst_dp[output_vec_idx] & 0x8000000000000000ULL) ? True : False;
832    memcpy(&res_dp, &dst_dp[output_vec_idx], 8);
833 
834 
835    // Below are common rules
836    if (isnan(src_dp))
837       return isnan(res_dp);
838    if (fpclassify(src_dp) == FP_ZERO)
839       return isinf(res_dp);
840    if (!src_is_negative && isinf(src_dp))
841       return !res_is_negative && (fpclassify(res_dp) == FP_ZERO);
842    if (is_rsqrte) {
843       if (src_is_negative)
844          return isnan(res_dp);
845    } else {
846       if (src_is_negative && isinf(src_dp))
847          return res_is_negative && (fpclassify(res_dp) == FP_ZERO);
848    }
849 
850    if (is_rsqrte)
851       recip_divisor = sqrt(src_dp);
852    else
853       recip_divisor = src_dp;
854 
855    /* The instructions handled by this function take a double precision
856     * input, perform a reciprocal estimate in double-precision, round
857     * the result to single precision and store into the destination
858     * register in double precision format.  So, to check the result
859     * for accuracy, we use float (single precision) values.
860     */
861    div_result = 1.0/recip_divisor;
862    calc_diff_tmp = recip_divisor * 16384.0;
863    if (isnormal(calc_diff_tmp)) {
864       calc_diff = fabs(1.0/calc_diff_tmp);
865       real_diff = fabs((float)res_dp - div_result);
866       result = ( ( res_dp == div_result )
867                || ( real_diff <= calc_diff ) );
868 #if FRES_DEBUG
869       unsigned int * dv = (unsigned int *)&div_result;
870       unsigned int * rd = (unsigned int *)&real_diff;
871       unsigned int * cd = (unsigned int *)&calc_diff;
872       printf("\n\t {computed div_result: %08x; real_diff:  %08x; calc_diff:  %08x}\n",
873              *dv, *rd, *cd);
874 #endif
875 
876    } else {
877       /* Unable to compute theoretical difference, so we fall back to masking out
878        * un-precise bits.
879        */
880       unsigned int * div_result_sp = (unsigned int *)&div_result;
881       float res_sp = (float)res_dp;
882       unsigned int * dst_sp = (unsigned int *)&res_sp;
883 #if FRES_DEBUG
884       unsigned int * calc_diff_tmp_sp = (unsigned int *)&calc_diff_tmp;
885       printf("Unable to compute theoretical difference, so we fall back to masking\n");
886       printf("\tcalc_diff_tmp: %08x; div_result: %08x; vector result (sp): %08x\n",
887              *calc_diff_tmp_sp, *div_result_sp, *dst_sp);
888 #endif
889       result = (*dst_sp & VSX_RECIP_ESTIMATE_MASK_SP) == (*div_result_sp & VSX_RECIP_ESTIMATE_MASK_SP);
890    }
891    return result;
892 }
893 
test_vx_fp_ops(void)894 static void test_vx_fp_ops(void)
895 {
896 
897    test_func_t func;
898    int k;
899    char * test_name = (char *)malloc(20);
900    void  * vecA_void_ptr, * vecB_void_ptr, * vecOut_void_ptr;
901 
902    if (isLE) {
903       vecA_void_ptr = (void *)&vec_inA + 8;
904       vecB_void_ptr = (void *)&vec_inB + 8;
905       vecOut_void_ptr = (void *)&vec_out + 8;
906    } else {
907       vecA_void_ptr = (void *)&vec_inA;
908       vecB_void_ptr = (void *)&vec_inB;
909       vecOut_void_ptr = (void *)&vec_out;
910    }
911 
912    k = 0;
913    build_special_fargs_table();
914    while ((func = vx_fp_tests[k].test_func)) {
915       int i, repeat = 0;
916       unsigned long long * frap, * frbp, * dst;
917       vx_fp_test_basic_t test_group = vx_fp_tests[k];
918       vx_fp_test_type test_type = test_group.test_type;
919 
920       switch (test_type) {
921          case VX_FP_SMAS:
922          case VX_FP_SMSS:
923          case VX_FP_SNMAS:
924          case VX_FP_SNMSS:
925             if (test_type == VX_FP_SMAS)
926                strcpy(test_name, "xsmadd");
927             else if (test_type == VX_FP_SMSS)
928                strcpy(test_name, "xsmsub");
929             else if (test_type == VX_FP_SNMAS)
930                strcpy(test_name, "xsnmadd");
931             else
932                strcpy(test_name, "xsnmsub");
933 
934             if (!repeat) {
935                repeat = 1;
936                strcat(test_name, "asp");
937                do_asp = 1;
938             }
939             break;
940          case VX_FP_OTHER:
941             strcpy(test_name, test_group.name);
942             break;
943          default:
944             printf("ERROR:  Invalid VX FP test type %d\n", test_type);
945             exit(1);
946       }
947 
948 again:
949       for (i = 0; i < test_group.num_tests; i++) {
950          unsigned int * inA, * inB, * pv;
951 
952          fp_test_args_t aTest = test_group.targs[i];
953          inA = (unsigned int *)&spec_fargs[aTest.fra_idx];
954          inB = (unsigned int *)&spec_fargs[aTest.frb_idx];
955          frap = (unsigned long long *)&spec_fargs[aTest.fra_idx];
956          frbp = (unsigned long long *)&spec_fargs[aTest.frb_idx];
957          int idx;
958          unsigned long long vsr_XT;
959          pv = (unsigned int *)&vec_out;
960 
961          // Only need to copy one doubleword into each vector's element 0
962          memcpy(vecA_void_ptr, inA, 8);
963          memcpy(vecB_void_ptr, inB, 8);
964 
965          // clear vec_out
966          for (idx = 0; idx < 4; idx++, pv++)
967             *pv = 0;
968 
969          if (test_type != VX_FP_OTHER) {
970             /* Then we need a third src argument, which is stored in element 0 of
971              * VSX[XT] -- i.e., vec_out.  For the xs<ZZZ>mdp cases, VSX[XT] holds
972              * src3 and VSX[XB] holds src2; for the xs<ZZZ>adp cases, VSX[XT] holds
973              * src2 and VSX[XB] holds src3.  The fp_test_args_t that holds the test
974              * data (input args, result) contain only two inputs, so I arbitrarily
975              * use spec_fargs elements 4 and 14 (alternating) for the third source
976              * argument.  We can use the same input data for a given pair of
977              * adp/mdp-type instructions by swapping the src2 and src3 arguments; thus
978              * the expected result should be the same.
979              */
980             int extra_arg_idx;
981             if (i % 2)
982                extra_arg_idx = 4;
983             else
984                extra_arg_idx = 14;
985 
986             if (repeat) {
987                /* We're on the first time through of one of the VX_FP_SMx
988                 * test types, meaning we're testing a xs<ZZZ>adp case, thus
989                 * we have to swap inputs as described above:
990                 *    src2 <= VSX[XT]
991                 *    src3 <= VSX[XB]
992                 */
993                memcpy(vecOut_void_ptr, inB, 8);  // src2
994                memcpy(vecB_void_ptr, &spec_fargs[extra_arg_idx], 8);  //src3
995                frbp = (unsigned long long *)&spec_fargs[extra_arg_idx];
996             } else {
997                // Don't need to init src2, as it's done before the switch()
998                memcpy(vecOut_void_ptr, &spec_fargs[extra_arg_idx], 8);  //src3
999             }
1000             memcpy(&vsr_XT, vecOut_void_ptr, 8);
1001          }
1002 
1003          (*func)();
1004          dst = (unsigned long long *) &vec_out;
1005          if (isLE)
1006             dst++;
1007 
1008          if (test_type == VX_FP_OTHER)
1009             printf("#%d: %s %016llx %016llx = %016llx\n", i, test_name,
1010                    *frap, *frbp, *dst);
1011          else
1012             printf( "#%d: %s %016llx %016llx %016llx = %016llx\n", i,
1013                     test_name, vsr_XT, *frap, *frbp, *dst );
1014 
1015       }
1016       /*
1017            {
1018                // Debug code.  Keep this block commented out except when debugging.
1019                double result, expected;
1020                memcpy(&result, dst, 8);
1021                memcpy(&expected, &aTest.dp_bin_result, 8);
1022                printf( "\tFRA + FRB: %e + %e: Expected = %e; Actual = %e\n",
1023                        spec_fargs[aTest.fra_idx], spec_fargs[aTest.frb_idx],
1024                        expected, result );
1025             }
1026        */
1027       printf( "\n" );
1028 
1029       if (repeat) {
1030          repeat = 0;
1031          strcat(test_name, "UNKNOWN");
1032          switch (test_type) {
1033             case VX_FP_SMAS:
1034             case VX_FP_SMSS:
1035             case VX_FP_SNMAS:
1036             case VX_FP_SNMSS:
1037                if (test_type == VX_FP_SMAS)
1038                   strcpy(test_name, "xsmadd");
1039                else if (test_type == VX_FP_SMSS)
1040                   strcpy(test_name, "xsmsub");
1041                else if (test_type == VX_FP_SNMAS)
1042                   strcpy(test_name, "xsnmadd");
1043                else
1044                   strcpy(test_name, "xsnmsub");
1045 
1046                do_asp = 0;
1047                strcat(test_name, "msp");
1048                break;
1049             default:
1050                break;
1051          }
1052          goto again;
1053       }
1054       k++;
1055    }
1056    printf( "\n" );
1057    free(test_name);
1058 }
1059 
1060 
test_vsx_one_fp_arg(void)1061 static void test_vsx_one_fp_arg(void)
1062 {
1063    test_func_t func;
1064    int k;
1065    void  * vecB_void_ptr;
1066 
1067    k = 0;
1068    build_special_fargs_table();
1069 
1070    while ((func = vsx_one_fp_arg_tests[k].test_func)) {
1071       int idx, i;
1072       unsigned long long *dst_dp;
1073       unsigned int * dst_sp;
1074       vx_fp_test2_t test_group = vsx_one_fp_arg_tests[k];
1075       /* size of source operands */
1076       Bool dp  = ((test_group.precision == DOUBLE_TEST) ||
1077 		  (test_group.precision == DOUBLE_TEST_SINGLE_RES)) ? True : False;
1078       /* size of result */
1079       Bool dp_res = IS_DP_RESULT(test_group.precision);
1080       Bool is_sqrt = (strstr(test_group.name, "sqrt")) ? True : False;
1081 
1082       vecB_void_ptr = (void *)&vec_inB;
1083       if (isLE) {
1084          vecB_void_ptr += dp? 8 : 12;
1085       }
1086 
1087       for (i = 0; i < test_group.num_tests; i++) {
1088          unsigned int * pv;
1089          void * inB;
1090 
1091          pv = (unsigned int *)&vec_out;
1092          // clear vec_out
1093          for (idx = 0; idx < 4; idx++, pv++)
1094             *pv = 0;
1095 
1096          if (dp) {
1097             int vec_out_idx;
1098             unsigned long long * frB_dp;
1099             if (isLE)
1100                vec_out_idx = dp_res ? 1 : 3;
1101             else
1102                vec_out_idx = 0;
1103 
1104             if (test_group.test_type == VX_SCALAR_SP_TO_VECTOR_SP) {
1105                /* Take a single-precision value stored in double word element 0
1106                 * of src in double-precision format and convert to single-
1107                 * precision and store in word element 0 of dst.
1108                 */
1109                double input = spec_sp_fargs[i];
1110                memcpy(vecB_void_ptr, (void *)&input, 8);
1111             } else {
1112                inB = (void *)&spec_fargs[i];
1113                // copy double precision FP into input vector element 0
1114                memcpy(vecB_void_ptr, inB, 8);
1115             }
1116 
1117             // execute test insn
1118             (*func)();
1119             if (dp_res)
1120                dst_dp = (unsigned long long *) &vec_out;
1121             else
1122                dst_sp = (unsigned int *) &vec_out;
1123 
1124             printf("#%d: %s ", i, test_group.name);
1125             frB_dp = (unsigned long long *)&spec_fargs[i];
1126             printf("%s(%016llx)", test_group.op, *frB_dp);
1127             if (test_group.test_type == VX_ESTIMATE)
1128             {
1129                Bool res;
1130                res = check_reciprocal_estimate(is_sqrt, i, vec_out_idx);
1131                printf(" ==> %s)", res ? "PASS" : "FAIL");
1132             } else if (dp_res) {
1133                printf(" = %016llx", dst_dp[vec_out_idx]);
1134             } else {
1135                printf(" = %08x", dst_sp[vec_out_idx]);
1136             }
1137 
1138             printf("\n");
1139          } else {  // single precision test type
1140             int vec_out_idx;
1141             if (isLE)
1142                vec_out_idx = dp_res ? 1 : 3;
1143             else
1144                vec_out_idx = 0;
1145             // Clear input vector
1146             pv = (unsigned int *)&vec_inB;
1147             for (idx = 0; idx < 4; idx++, pv++)
1148                *pv = 0;
1149             inB = (void *)&spec_sp_fargs[i];
1150             // copy single precision FP into input vector element i
1151             memcpy(vecB_void_ptr, inB, 4);
1152             // execute test insn
1153             (*func)();
1154             if (dp_res)
1155                dst_dp = (unsigned long long *) &vec_out;
1156             else
1157                dst_sp = (unsigned int *) &vec_out;
1158             // print result
1159             printf("#%d: %s ", i, test_group.name);
1160                printf("%s(%08x)", test_group.op, *((unsigned int *)&spec_sp_fargs[i]));
1161                if (dp_res)
1162                      printf(" = %016llx", dst_dp[vec_out_idx]);
1163                else
1164                   printf(" = %08x", dst_sp[vec_out_idx]);
1165 
1166             printf("\n");
1167          }
1168       }
1169       k++;
1170       printf( "\n" );
1171    }
1172 }
1173 
1174 /* This function currently only supports two double precision input arguments. */
test_vsx_two_fp_arg(void)1175 static void test_vsx_two_fp_arg(void)
1176 {
1177    test_func_t func;
1178    int k = 0;
1179    void  * vecA_void_ptr, * vecB_void_ptr;
1180 
1181    if (isLE) {
1182       vecA_void_ptr = (void *)&vec_inA + 8;
1183       vecB_void_ptr = (void *)&vec_inB + 8;
1184    } else {
1185       vecA_void_ptr = (void *)&vec_inA;
1186       vecB_void_ptr = (void *)&vec_inB;
1187    }
1188 
1189    build_special_fargs_table();
1190    while ((func = vx_simple_scalar_fp_tests[k].test_func)) {
1191       unsigned long long * frap, * frbp, * dst;
1192       unsigned int * pv;
1193       int idx;
1194       vx_fp_test_basic_t test_group = vx_simple_scalar_fp_tests[k];
1195       pv = (unsigned int *)&vec_out;
1196       // clear vec_out
1197       for (idx = 0; idx < 4; idx++, pv++)
1198          *pv = 0;
1199 
1200       void * inA, * inB;
1201       int i;
1202       for (i = 0; i < test_group.num_tests; i++) {
1203          fp_test_args_t aTest = test_group.targs[i];
1204          inA = (void *)&spec_fargs[aTest.fra_idx];
1205          inB = (void *)&spec_fargs[aTest.frb_idx];
1206          frap = (unsigned long long *)&spec_fargs[aTest.fra_idx];
1207          frbp = (unsigned long long *)&spec_fargs[aTest.frb_idx];
1208          // Only need to copy one doubleword into each vector's element 0
1209          memcpy(vecA_void_ptr, inA, 8);
1210          memcpy(vecB_void_ptr, inB, 8);
1211          (*func)();
1212          dst = (unsigned long long *) &vec_out;
1213          if (isLE)
1214             dst++;
1215          printf("#%d: %s %016llx,%016llx => %016llx\n", i, test_group.name,
1216                 *frap, *frbp, *dst);
1217       }
1218       printf( "\n" );
1219       k++;
1220    }
1221 }
1222 
1223 /* This function handles the following cases:
1224  *   1) Single precision value stored in double-precision
1225  *      floating-point format in doubleword element 0 of src VSX register
1226  *   2) Integer word value stored in word element 1 of src VSX register
1227  */
_do_store_test(ldst_test_t storeTest)1228 static void _do_store_test (ldst_test_t storeTest)
1229 {
1230    test_func_t func;
1231    unsigned int *dst32;
1232    unsigned int i, idx;
1233    unsigned int * pv = (unsigned int *) storeTest.base_addr;
1234    void  * vecA_void_ptr;
1235 
1236    if (isLE) {
1237       if (storeTest.precision == SINGLE_TEST_SINGLE_RES)
1238          vecA_void_ptr = (void *)&vec_inA + 8;
1239    } else {
1240       if (storeTest.precision == SINGLE_TEST_SINGLE_RES)
1241          vecA_void_ptr = (void *)&vec_inA + 4;
1242       else
1243          vecA_void_ptr = (void *)&vec_inA;
1244    }
1245 
1246    func = storeTest.test_func;
1247    r14 = (HWord_t) storeTest.base_addr;
1248    r15 = (HWord_t) storeTest.offset;
1249 
1250    /* test some of the pre-defined single precision values */
1251    for (i = 0; i < nb_special_fargs; i+=3) {
1252       // clear out storage destination
1253       for (idx = 0; idx < 4; idx++)
1254          *(pv + idx) = 0;
1255 
1256       printf( "%s:", storeTest.name );
1257       if (storeTest.precision == SINGLE_TEST_SINGLE_RES)
1258       {
1259          unsigned int * arg_ptr = (unsigned int *)&spec_sp_fargs[i];
1260          memcpy(vecA_void_ptr, arg_ptr, sizeof(unsigned int));
1261          printf(" %08x ==> ", *arg_ptr);
1262       } else {
1263          unsigned long long * dp;
1264          double input = spec_sp_fargs[i];
1265          dp = (unsigned long long *)&input;
1266          memcpy(vecA_void_ptr, dp, sizeof(unsigned long long));
1267          printf(" %016llx ==> ", *dp);
1268       }
1269 
1270       // execute test insn
1271       (*func)();
1272       dst32 = (unsigned int*)(storeTest.base_addr);
1273       dst32 += (storeTest.offset/sizeof(int));
1274       printf( "%08x\n", *dst32);
1275    }
1276 
1277    printf("\n");
1278 }
1279 
_do_load_test(ldst_test_t loadTest)1280 static void _do_load_test(ldst_test_t loadTest)
1281 {
1282    test_func_t func;
1283    unsigned int i;
1284    unsigned long long * dst_dp;
1285 
1286    func = loadTest.test_func;
1287    r15 = (HWord_t) loadTest.offset;
1288 
1289    if (loadTest.base_addr == NULL) {
1290       /* Test lxsspx: source is single precision value, so let's */
1291       /* test some of the pre-defined single precision values. */
1292       int num_loops = (loadTest.offset == 0) ?  nb_special_fargs : (nb_special_fargs - (loadTest.offset/sizeof(int)));
1293       for (i = 0; i < num_loops; i+=3) {
1294          unsigned int * sp = (unsigned int *)&spec_sp_fargs[i + (loadTest.offset/sizeof(int))];
1295          printf( "%s:", loadTest.name );
1296          printf(" %08x ==> ", *sp);
1297          r14 = (HWord_t)&spec_sp_fargs[i];
1298 
1299          // execute test insn
1300          (*func)();
1301          dst_dp = (unsigned long long *) &vec_out;
1302          if (isLE)
1303             dst_dp++;
1304          printf("%016llx\n", *dst_dp);
1305       }
1306    } else {
1307       // source is an integer word
1308       int num_loops = (loadTest.offset == 0) ?  NUM_VIARGS_INTS : (NUM_VIARGS_INTS - (loadTest.offset/sizeof(int)));
1309       for (i = 0; i < num_loops; i++) {
1310          printf( "%s:", loadTest.name );
1311          r14 = (HWord_t)&viargs[i];
1312          printf(" %08x ==> ", viargs[i + (loadTest.offset/sizeof(int))]);
1313 
1314          // execute test insn
1315          (*func)();
1316          dst_dp = (unsigned long long *) &vec_out;
1317          if (isLE)
1318             dst_dp++;
1319          printf("%016llx\n", *dst_dp);
1320       }
1321    }
1322    printf("\n");
1323 }
1324 
test_ldst(void)1325 static void test_ldst(void)
1326 {
1327    int k = 0;
1328 
1329    while (ldst_tests[k].test_func) {
1330       if (ldst_tests[k].type == VSX_STORE)
1331          _do_store_test(ldst_tests[k]);
1332       else {
1333          _do_load_test(ldst_tests[k]);
1334       }
1335       k++;
1336       printf("\n");
1337    }
1338 }
1339 
test_xs_conv_ops(void)1340 static void test_xs_conv_ops(void)
1341 {
1342 
1343    test_func_t func;
1344    int k = 0;
1345    void  * vecB_void_ptr;
1346 
1347    if (isLE)
1348       vecB_void_ptr = (void *)&vec_inB + 8;
1349    else
1350       vecB_void_ptr = (void *)&vec_inB;
1351 
1352    build_special_fargs_table();
1353    while ((func = xs_conv_tests[k].test_func)) {
1354       int i;
1355       unsigned long long * dst;
1356       xs_conv_test_t test_group = xs_conv_tests[k];
1357       for (i = 0; i < NUM_VDARGS_INTS; i++) {
1358          unsigned long long  * inB, * pv;
1359          int idx;
1360          inB = (unsigned long long *)&vdargs[i];
1361          memcpy(vecB_void_ptr, inB, 8);
1362          pv = (unsigned long long *)&vec_out;
1363          // clear vec_out
1364          for (idx = 0; idx < 2; idx++, pv++)
1365             *pv = 0ULL;
1366          (*func)();
1367          dst = (unsigned long long *) &vec_out;
1368          if (isLE)
1369             dst++;
1370          printf("#%d: %s %016llx => %016llx\n", i, test_group.name, vdargs[i], *dst);
1371       }
1372       k++;
1373       printf("\n");
1374    }
1375    printf( "\n" );
1376 }
1377 
1378 
test_vsx_logic(void)1379 static void test_vsx_logic(void)
1380 {
1381    logic_test_t aTest;
1382    test_func_t func;
1383    int k;
1384    k = 0;
1385 
1386    while ((func = logic_tests[k].test_func)) {
1387 
1388       unsigned int * pv;
1389       unsigned int * inA, * inB, * dst;
1390       int idx, i;
1391       aTest = logic_tests[k];
1392       for (i = 0; i <= NUM_VIARGS_VECS; i+=4) {
1393          pv = (unsigned int *)&vec_out;
1394          inA = &viargs[i];
1395          inB = &viargs[i];
1396          memcpy(&vec_inA, inA, sizeof(vector unsigned int));
1397          memcpy(&vec_inB, inB, sizeof(vector unsigned int));
1398          // clear vec_out
1399          for (idx = 0; idx < 4; idx++, pv++)
1400             *pv = 0;
1401 
1402          // execute test insn
1403          (*func)();
1404          dst = (unsigned int*) &vec_out;
1405 
1406          printf( "#%d: %10s ", k, aTest.name);
1407          printf( " (%08x %08x %08x %08x, ", inA[0], inA[1], inA[2], inA[3]);
1408          printf( " %08x %08x %08x %08x)", inB[0], inB[1], inB[2], inB[3]);
1409          printf(" ==> %08x %08x %08x %08x\n", dst[0], dst[1], dst[2], dst[3]);
1410       }
1411       k++;
1412    }
1413    printf( "\n" );
1414 }
1415 
1416 
1417 //----------------------------------------------------------
1418 
1419 static test_table_t all_tests[] = {
1420                                      { &test_vx_fp_ops,
1421                                        "Test VSX floating point instructions"},
1422                                      { &test_vsx_one_fp_arg,
1423                                        "Test VSX vector and scalar single argument instructions"} ,
1424                                      { &test_vsx_logic,
1425                                        "Test VSX logic instructions" },
1426                                      { &test_xs_conv_ops,
1427                                        "Test VSX scalar integer conversion instructions" },
1428                                      { &test_ldst,
1429                                        "Test VSX load/store dp to sp instructions" },
1430                                      { &test_vsx_two_fp_arg,
1431                                        "Test VSX vector and scalar two argument instructions"} ,
1432                                      { NULL, NULL }
1433 };
1434 
1435 #endif
1436 
main(int argc,char * argv[])1437 int main(int argc, char *argv[])
1438 {
1439 
1440 #ifdef HAS_ISA_2_07
1441    test_table_t aTest;
1442    test_func_t func;
1443    int i = 0;
1444 
1445    while ((func = all_tests[i].test_category)) {
1446       aTest = all_tests[i];
1447       printf( "%s\n", aTest.name );
1448       (*func)();
1449       i++;
1450    }
1451 #else
1452    printf("NO ISA 2.07 SUPPORT\n");
1453 #endif
1454    return 0;
1455 }
1456