Home | History | Annotate | Download | only in ppc32
      1 /*  Copyright (C) 2012 IBM
      2 
      3  Author: Maynard Johnson <maynardj (at) 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 #include <stdio.h>
     24 #include <stdlib.h>
     25 #include <stdint.h>
     26 
     27 #if defined(HAS_DFP)
     28 
     29 typedef union stuff {
     30    _Decimal64  dec_val;
     31    _Decimal128  dec_val128;
     32    unsigned long long u64_val;
     33    struct {
     34 #if defined(VGP_ppc64le_linux)
     35       unsigned long long vall;
     36       unsigned long long valu;
     37 #else
     38       unsigned long long valu;
     39       unsigned long long vall;
     40 #endif
     41    } u128;
     42 } dfp_val_t;
     43 
     44 
     45 typedef unsigned char Bool;
     46 #define True 1
     47 #define False 0
     48 
     49 
     50 #define ALLCR "cr0","cr1","cr2","cr3","cr4","cr5","cr6","cr7"
     51 
     52 #define SET_CR(_arg) \
     53       __asm__ __volatile__ ("mtcr  %0" : : "b"(_arg) : ALLCR );
     54 
     55 #define SET_XER(_arg) \
     56       __asm__ __volatile__ ("mtxer %0" : : "b"(_arg) : "xer" );
     57 
     58 #define GET_CR(_lval) \
     59       __asm__ __volatile__ ("mfcr %0"  : "=b"(_lval) )
     60 
     61 #define GET_XER(_lval) \
     62       __asm__ __volatile__ ("mfxer %0" : "=b"(_lval) )
     63 
     64 #define GET_CR_XER(_lval_cr,_lval_xer) \
     65    do { GET_CR(_lval_cr); GET_XER(_lval_xer); } while (0)
     66 
     67 #define SET_CR_ZERO \
     68       SET_CR(0)
     69 
     70 #define SET_XER_ZERO \
     71       SET_XER(0)
     72 
     73 #define SET_CR_XER_ZERO \
     74    do { SET_CR_ZERO; SET_XER_ZERO; } while (0)
     75 
     76 #define SET_FPSCR_ZERO \
     77    do { double _d = 0.0; \
     78         __asm__ __volatile__ ("mtfsf 0xFF, %0" : : "f"(_d) ); \
     79    } while (0)
     80 
     81 #define GET_FPSCR(_arg) \
     82     __asm__ __volatile__ ("mffs %0"  : "=f"(_arg) )
     83 
     84 #define SET_FPSCR_DRN \
     85     __asm__ __volatile__ ("mtfsf  1, %0, 0, 1" :  : "f"(f14) )
     86 
     87 
     88 // The assembly-level instructions being tested
     89 
     90 /* In _test_dtstdc[q], DCM can be one of 6 possible data classes, numbered 0-5.
     91  * In reality, DCM is a 6-bit mask field.  We just test the individual values
     92  * and assume that masking multiple values would work OK.
     93  * BF is the condition register bit field which can range from 0-7.  But for
     94  * testing purposes, we only use BF values of '0' and '5'.
     95  */
     96 static void _test_dtstdc(int BF, int DCM, dfp_val_t *val1, dfp_val_t *x1 __attribute__((unused)))
     97 {
     98    _Decimal64 f14 = val1->dec_val;
     99    if (DCM < 0 || DCM > 5 || !(BF == 0 || BF == 5)) {
    100       fprintf(stderr, "Invalid inputs to asm test: a=%d, b=%d\n", BF, DCM);
    101       return;
    102    }
    103    switch (DCM) {
    104       case 0:
    105          if (BF)
    106             __asm__ __volatile__ ("dtstdc 5, %0, 1" : : "f" (f14));
    107          else
    108             __asm__ __volatile__ ("dtstdc 0, %0, 1" : : "f" (f14));
    109          break;
    110       case 1:
    111          if (BF)
    112             __asm__ __volatile__ ("dtstdc 5, %0, 2" : : "f" (f14));
    113          else
    114             __asm__ __volatile__ ("dtstdc 0, %0, 2" : : "f" (f14));
    115          break;
    116       case 2:
    117          if (BF)
    118             __asm__ __volatile__ ("dtstdc 5, %0, 4" : : "f" (f14));
    119          else
    120             __asm__ __volatile__ ("dtstdc 0, %0, 4" : : "f" (f14));
    121          break;
    122       case 3:
    123          if (BF)
    124             __asm__ __volatile__ ("dtstdc 5, %0, 8" : : "f" (f14));
    125          else
    126             __asm__ __volatile__ ("dtstdc 0, %0, 8" : : "f" (f14));
    127          break;
    128       case 4:
    129          if (BF)
    130             __asm__ __volatile__ ("dtstdc 5, %0, 16" : : "f" (f14));
    131          else
    132             __asm__ __volatile__ ("dtstdc 0, %0, 16" : : "f" (f14));
    133          break;
    134       case 5:
    135          if (BF)
    136             __asm__ __volatile__ ("dtstdc 5, %0, 32" : : "f" (f14));
    137          else
    138             __asm__ __volatile__ ("dtstdc 0, %0, 32" : : "f" (f14));
    139          break;
    140       default:
    141          break;
    142    }
    143 }
    144 
    145 static void _test_dtstdcq(int BF, int DCM, dfp_val_t *val1, dfp_val_t *x1 __attribute__((unused)))
    146 {
    147    _Decimal128 f14 = val1->dec_val128;
    148    if (DCM < 0 || DCM > 5 || !(BF == 0 || BF == 5)) {
    149       fprintf(stderr, "Invalid inputs to asm test: a=%d, b=%d\n", BF, DCM);
    150       return;
    151    }
    152    switch (DCM) {
    153       case 0:
    154          if (BF)
    155             __asm__ __volatile__ ("dtstdcq 5, %0, 1" : : "f" (f14));
    156          else
    157             __asm__ __volatile__ ("dtstdcq 0, %0, 1" : : "f" (f14));
    158          break;
    159       case 1:
    160          if (BF)
    161             __asm__ __volatile__ ("dtstdcq 5, %0, 2" : : "f" (f14));
    162          else
    163             __asm__ __volatile__ ("dtstdcq 0, %0, 2" : : "f" (f14));
    164          break;
    165       case 2:
    166          if (BF)
    167             __asm__ __volatile__ ("dtstdcq 5, %0, 4" : : "f" (f14));
    168          else
    169             __asm__ __volatile__ ("dtstdcq 0, %0, 4" : : "f" (f14));
    170          break;
    171       case 3:
    172          if (BF)
    173             __asm__ __volatile__ ("dtstdcq 5, %0, 8" : : "f" (f14));
    174          else
    175             __asm__ __volatile__ ("dtstdcq 0, %0, 8" : : "f" (f14));
    176          break;
    177       case 4:
    178          if (BF)
    179             __asm__ __volatile__ ("dtstdcq 5, %0, 16" : : "f" (f14));
    180          else
    181             __asm__ __volatile__ ("dtstdcq 0, %0, 16" : : "f" (f14));
    182          break;
    183       case 5:
    184          if (BF)
    185             __asm__ __volatile__ ("dtstdcq 5, %0, 32" : : "f" (f14));
    186          else
    187             __asm__ __volatile__ ("dtstdcq 0, %0, 32" : : "f" (f14));
    188          break;
    189       default:
    190          break;
    191    }
    192 }
    193 
    194 /* In _test_dtstdg[q], DGM can be one of 6 possible data groups, numbered 0-5.
    195  * In reality, DGM is a 6-bit mask field.  We just test the individual values
    196  * and assume that masking multiple values would work OK.
    197  * BF is the condition register bit field which can range from 0-7.  But for
    198  * testing purposes, we only use BF values of '0' and '5'.
    199  */
    200 static void _test_dtstdg(int BF, int DGM, dfp_val_t *val1, dfp_val_t *x1 __attribute__((unused)))
    201 {
    202    _Decimal64 f14 = val1->dec_val;
    203    if (DGM < 0 || DGM > 5 || !(BF == 0 || BF == 5)) {
    204       fprintf(stderr, "Invalid inputs to asm test: a=%d, b=%d\n", BF, DGM);
    205       return;
    206    }
    207    switch (DGM) {
    208       case 0:
    209          if (BF)
    210             __asm__ __volatile__ ("dtstdg 5, %0, 1" : : "f" (f14));
    211          else
    212             __asm__ __volatile__ ("dtstdg 0, %0, 1" : : "f" (f14));
    213          break;
    214       case 1:
    215          if (BF)
    216             __asm__ __volatile__ ("dtstdg 5, %0, 2" : : "f" (f14));
    217          else
    218             __asm__ __volatile__ ("dtstdg 0, %0, 2" : : "f" (f14));
    219          break;
    220       case 2:
    221          if (BF)
    222             __asm__ __volatile__ ("dtstdg 5, %0, 4" : : "f" (f14));
    223          else
    224             __asm__ __volatile__ ("dtstdg 0, %0, 4" : : "f" (f14));
    225          break;
    226       case 3:
    227          if (BF)
    228             __asm__ __volatile__ ("dtstdg 5, %0, 8" : : "f" (f14));
    229          else
    230             __asm__ __volatile__ ("dtstdg 0, %0, 8" : : "f" (f14));
    231          break;
    232       case 4:
    233          if (BF)
    234             __asm__ __volatile__ ("dtstdg 5, %0, 16" : : "f" (f14));
    235          else
    236             __asm__ __volatile__ ("dtstdg 0, %0, 16" : : "f" (f14));
    237          break;
    238       case 5:
    239          if (BF)
    240             __asm__ __volatile__ ("dtstdg 5, %0, 32" : : "f" (f14));
    241          else
    242             __asm__ __volatile__ ("dtstdg 0, %0, 32" : : "f" (f14));
    243          break;
    244       default:
    245          break;
    246    }
    247 }
    248 
    249 static void _test_dtstdgq(int BF, int DGM, dfp_val_t *val1, dfp_val_t *x1 __attribute__((unused)))
    250 {
    251    _Decimal128 f14 = val1->dec_val128;
    252    if (DGM < 0 || DGM > 5 || !(BF == 0 || BF == 5)) {
    253       fprintf(stderr, "Invalid inputs to asm test: a=%d, b=%d\n", BF, DGM);
    254       return;
    255    }
    256    switch (DGM) {
    257       case 0:
    258          if (BF)
    259             __asm__ __volatile__ ("dtstdgq 5, %0, 1" : : "f" (f14));
    260          else
    261             __asm__ __volatile__ ("dtstdgq 0, %0, 1" : : "f" (f14));
    262          break;
    263       case 1:
    264          if (BF)
    265             __asm__ __volatile__ ("dtstdgq 5, %0, 2" : : "f" (f14));
    266          else
    267             __asm__ __volatile__ ("dtstdgq 0, %0, 2" : : "f" (f14));
    268          break;
    269       case 2:
    270          if (BF)
    271             __asm__ __volatile__ ("dtstdgq 5, %0, 4" : : "f" (f14));
    272          else
    273             __asm__ __volatile__ ("dtstdgq 0, %0, 4" : : "f" (f14));
    274          break;
    275       case 3:
    276          if (BF)
    277             __asm__ __volatile__ ("dtstdgq 5, %0, 8" : : "f" (f14));
    278          else
    279             __asm__ __volatile__ ("dtstdgq 0, %0, 8" : : "f" (f14));
    280          break;
    281       case 4:
    282          if (BF)
    283             __asm__ __volatile__ ("dtstdgq 5, %0, 16" : : "f" (f14));
    284          else
    285             __asm__ __volatile__ ("dtstdgq 0, %0, 16" : : "f" (f14));
    286          break;
    287       case 5:
    288          if (BF)
    289             __asm__ __volatile__ ("dtstdgq 5, %0, 32" : : "f" (f14));
    290          else
    291             __asm__ __volatile__ ("dtstdgq 0, %0, 32" : : "f" (f14));
    292          break;
    293       default:
    294          break;
    295    }
    296 }
    297 
    298 /* In _test_dtstex[q], BF is the condition register bit field indicating the
    299  * CR field in which the result of the test should be placed.  BF can range
    300  * from 0-7, but for testing purposes, we only use BF values of '4' and '7'.
    301  */
    302 static void
    303 _test_dtstex(int BF, int x __attribute__((unused)), dfp_val_t *val1, dfp_val_t *val2)
    304 {
    305    _Decimal64 f14 = val1->dec_val;
    306    _Decimal64 f16 = val2->dec_val;
    307    if (!(BF == 4 || BF == 7)) {
    308       fprintf(stderr, "Invalid input to asm test: a=%d\n", BF);
    309       return;
    310    }
    311    switch (BF) {
    312       case 4:
    313          __asm__ __volatile__ ("dtstex  4, %0, %1" :  : "f" (f14),"f" (f16));
    314          break;
    315       case 7:
    316          __asm__ __volatile__ ("dtstex  7, %0, %1" :  : "f" (f14),"f" (f16));
    317          break;
    318       default:
    319          break;
    320    }
    321 }
    322 
    323 static void _test_dtstexq(int BF, int x __attribute__((unused)), dfp_val_t *val1, dfp_val_t *val2)
    324 {
    325    _Decimal128 f14 = val1->dec_val128;
    326    _Decimal128 f16 = val2->dec_val128;
    327    if (!(BF == 4 || BF == 7)) {
    328       fprintf(stderr, "Invalid input to asm test: a=%d\n", BF);
    329       return;
    330    }
    331    switch (BF) {
    332       case 4:
    333          __asm__ __volatile__ ("dtstexq  4, %0, %1" :  : "f" (f14),"f" (f16));
    334          break;
    335       case 7:
    336          __asm__ __volatile__ ("dtstexq  7, %0, %1" :  : "f" (f14),"f" (f16));
    337          break;
    338       default:
    339          break;
    340    }
    341 }
    342 
    343 
    344 
    345 typedef void (*test_funcp_t)(int a, int b,  dfp_val_t *val1,  dfp_val_t *val2);
    346 typedef void (*test_driver_func_t)(void);
    347 typedef struct test_table
    348 {
    349    test_driver_func_t test_category;
    350    char * name;
    351 } test_table_t;
    352 
    353 /*
    354  *  345.0DD (0x2207c00000000000 0xe50)
    355  *  1.2300e+5DD (0x2207c00000000000 0x14c000)
    356  *  -16.0DD (0xa207c00000000000 0xe0)
    357  *  0.00189DD (0x2206c00000000000 0xcf)
    358  *  -4.1235DD (0xa205c00000000000 0x10a395bcf)
    359  *  9.8399e+20DD (0x2209400000000000 0x253f1f534acdd4)
    360  *  0DD (0x2208000000000000 0x0)
    361  *  0DD (0x2208000000000000 0x0)
    362  *  infDD (0x7800000000000000 0x0)
    363  *  nanDD (0x7c00000000000000 0x0
    364  */
    365 static unsigned long long dfp128_vals[] = {
    366                                     // Some finite numbers
    367                                     0x2207c00000000000ULL, 0x0000000000000e50ULL,
    368                                     0x2207c00000000000ULL, 0x000000000014c000ULL,
    369                                     0xa207c00000000000ULL, 0x00000000000000e0ULL,
    370                                     0x2206c00000000000ULL, 0x00000000000000cfULL,
    371                                     0xa205c00000000000ULL, 0x000000010a395bcfULL,
    372                                     0x6209400000fd0000ULL, 0x00253f1f534acdd4ULL, // huge number
    373                                     0x000400000089b000ULL, 0x0a6000d000000049ULL, // very small number
    374                                     // flavors of zero
    375                                     0x2208000000000000ULL, 0x0000000000000000ULL,
    376                                     0xa208000000000000ULL, 0x0000000000000000ULL, // negative
    377                                     0xa248000000000000ULL, 0x0000000000000000ULL,
    378                                     // flavors of NAN
    379                                     0x7c00000000000000ULL, 0x0000000000000000ULL, // quiet
    380                                     0xfc00000000000000ULL, 0xc00100035b007700ULL,
    381                                     0x7e00000000000000ULL, 0xfe000000d0e0a0d0ULL, // signaling
    382                                     // flavors of Infinity
    383                                     0x7800000000000000ULL, 0x0000000000000000ULL,
    384                                     0xf800000000000000ULL, 0x0000000000000000ULL, // negative
    385                                     0xf900000000000000ULL, 0x0000000000000000ULL
    386 };
    387 
    388 static unsigned long long dfp64_vals[] = {
    389                                  // various finite numbers
    390                                  0x2234000000000e50ULL,
    391                                  0x223400000014c000ULL,
    392                                  0xa2340000000000e0ULL,// negative
    393                                  0x22240000000000cfULL,
    394                                  0xa21400010a395bcfULL,// negative
    395                                  0x6e4d3f1f534acdd4ULL,// huge number
    396                                  0x000400000089b000ULL,// very small number
    397                                  // flavors of zero
    398                                  0x2238000000000000ULL,
    399                                  0xa238000000000000ULL,
    400                                  0x4248000000000000ULL,
    401                                  // flavors of NAN
    402                                  0x7e34000000000111ULL,
    403                                  0xfe000000d0e0a0d0ULL,//signaling
    404                                  0xfc00000000000000ULL,//quiet
    405                                  // flavors of Infinity
    406                                  0x7800000000000000ULL,
    407                                  0xf800000000000000ULL,//negative
    408                                  0x7a34000000000000ULL,
    409 };
    410 
    411 // Both Long and Quad arrays of DFP values should have the same length, so it
    412 // doesn't matter which array I use for calculating the following #define.
    413 #define NUM_DFP_VALS (sizeof(dfp64_vals)/8)
    414 
    415 typedef struct dfp_test_args {
    416    int fra_idx;
    417    int frb_idx;
    418 } dfp_test_args_t;
    419 
    420 
    421 // Index pairs from dfp64_vals array to be used with dfp_two_arg_tests
    422 static dfp_test_args_t dfp_2args_x1[] = {
    423                                     {0, 1},
    424                                     {2, 1},
    425                                     {4, 3},
    426                                     {6, 0},
    427                                     {2, 4},
    428                                     {5, 1},
    429                                     {5, 2},
    430                                     {7, 1},
    431                                     {7, 2},
    432                                     {8, 0},
    433                                     {8, 1},
    434                                     {8, 2},
    435                                     {7, 8},
    436                                     {12, 14},
    437                                     {12, 1},
    438                                     {12, 13},
    439                                     {12, 12},
    440                                     {12, 11},
    441                                     {11, 14},
    442                                     {11, 0},
    443                                     {11, 13},
    444                                     {11, 11},
    445                                     {14, 14},
    446                                     {14, 3},
    447                                     {14, 15},
    448 };
    449 
    450 typedef enum {
    451    LONG_TEST,
    452    QUAD_TEST
    453 } precision_type_t;
    454 
    455 typedef struct dfp_test
    456 {
    457    test_funcp_t test_func;
    458    const char * name;
    459    dfp_test_args_t * targs;
    460    int num_tests;
    461    precision_type_t precision;
    462    const char * op;
    463 } dfp_test_t;
    464 
    465 typedef struct dfp_one_arg_test
    466 {
    467    test_funcp_t test_func;
    468    const char * name;
    469    precision_type_t precision;
    470    const char * op;
    471 } dfp_one_arg_test_t;
    472 
    473 
    474 
    475 static dfp_one_arg_test_t
    476 dfp_ClassAndGroupTest_tests[] = {
    477                                  { &_test_dtstdc,  "dtstdc", LONG_TEST, "[tCls]"},
    478                                  { &_test_dtstdcq, "dtstdcq", QUAD_TEST, "[tCls]"},
    479                                  { &_test_dtstdg,  "dtstdg", LONG_TEST, "[tGrp]"},
    480                                  { &_test_dtstdgq, "dtstdgq", QUAD_TEST, "[tGrp]"},
    481                                  { NULL, NULL, 0, NULL}
    482 };
    483 
    484 static void test_dfp_ClassAndGroupTest_ops(void)
    485 {
    486    test_funcp_t func;
    487    dfp_val_t test_val, dummy;
    488 
    489    int k = 0;
    490 
    491    while ((func = dfp_ClassAndGroupTest_tests[k].test_func)) {
    492       int i;
    493       dfp_one_arg_test_t test_def = dfp_ClassAndGroupTest_tests[k];
    494 
    495       for (i = 0; i < NUM_DFP_VALS; i++) {
    496          int data_class_OR_group, BF = 0;
    497          Bool repeat = True;
    498 
    499          if (test_def.precision == LONG_TEST) {
    500             test_val.u64_val = dfp64_vals[i];
    501          } else {
    502             test_val.u128.valu = dfp128_vals[i * 2];
    503             test_val.u128.vall = dfp128_vals[(i * 2) + 1];
    504          }
    505 
    506 again:
    507          for (data_class_OR_group = 0; data_class_OR_group < 6; data_class_OR_group++) {
    508             unsigned int condreg;
    509             unsigned int flags;
    510             SET_FPSCR_ZERO;
    511             SET_CR_XER_ZERO;
    512 
    513 	    /* There is an ABI change in how 128 bit arguments are aligned
    514              * with GCC 5.0.  The compiler generates a "note" about this
    515              * starting with GCC 4.8.  To avoid generating the "note", pass
    516              * the address of the 128-bit arguments rather then the value.
    517 	     */
    518             (*func)(BF, data_class_OR_group, &test_val, &dummy);
    519             GET_CR(flags);
    520 
    521             condreg = ((flags >> (4 * (7-BF)))) & 0xf;
    522             printf("%s (DC/DG=%d) %s", test_def.name, data_class_OR_group,
    523                    test_def.op);
    524             if (test_def.precision == QUAD_TEST) {
    525                printf("%016llx %016llx", test_val.u128.valu, test_val.u128.vall);
    526             } else {
    527                printf("%016llx", test_val.u64_val);
    528             }
    529 
    530                //%016llx
    531             printf(" => %x (BF=%d)\n", condreg, BF);
    532          }
    533          if (repeat) {
    534             repeat = False;
    535             BF = 5;
    536             goto again;
    537          }
    538       }
    539       k++;
    540       printf( "\n" );
    541    }
    542 }
    543 
    544 
    545 static dfp_test_t
    546 dfp_ExpTest_tests[] = {
    547                    { &_test_dtstex, "dtstex", dfp_2args_x1, 25, LONG_TEST, "[tExp]"},
    548                    { &_test_dtstexq, "dtstexq", dfp_2args_x1, 25, QUAD_TEST, "[tExp]"},
    549                    { NULL, NULL, NULL, 0, 0, NULL}
    550 };
    551 
    552 
    553 static void test_dfp_ExpTest_ops(void)
    554 {
    555    dfp_val_t test_val1, test_val2;
    556    test_funcp_t func;
    557    int k = 0;
    558 
    559    while ((func = dfp_ExpTest_tests[k].test_func)) {
    560       /* BF is a 3-bit instruction field that indicates the CR field in which the
    561        * result of the test should be placed.  We won't iterate through all
    562        * 8 possible BF values since storing compare results to a given field is
    563        * a well-tested mechanism in VEX.  But we will test two BF values, just as
    564        * a sniff-test.
    565        */
    566       int i, repeat = 1, BF = 4;
    567       dfp_test_t test_def = dfp_ExpTest_tests[k];
    568 
    569 again:
    570       for (i = 0; i < test_def.num_tests; i++) {
    571          unsigned int condreg;
    572          unsigned int flags;
    573 
    574          if (test_def.precision == LONG_TEST) {
    575             test_val1.u64_val = dfp64_vals[test_def.targs[i].fra_idx];
    576             test_val2.u64_val  = dfp64_vals[test_def.targs[i].frb_idx];
    577          } else {
    578             test_val1.u128.valu = dfp128_vals[test_def.targs[i].fra_idx * 2];
    579             test_val1.u128.vall = dfp128_vals[(test_def.targs[i].fra_idx * 2) + 1];
    580             test_val2.u128.valu = dfp128_vals[test_def.targs[i].frb_idx * 2];
    581             test_val2.u128.vall = dfp128_vals[(test_def.targs[i].frb_idx * 2) + 1];
    582          }
    583 
    584          SET_FPSCR_ZERO;
    585          SET_CR_XER_ZERO;
    586          /* There is an ABI change in how 128 bit arguments are aligned
    587           * with GCC 5.0.  The compiler generates a "note" about this
    588           * starting with GCC 4.8.  To avoid generating the "note", pass
    589           * the address of the 128-bit arguments rather then the value.
    590           */
    591          (*func)(BF, 0, &test_val1, &test_val2);
    592          GET_CR(flags);
    593 
    594          condreg = ((flags >> (4 * (7-BF)))) & 0xf;
    595          printf("%s ", test_def.name);
    596          if (test_def.precision == LONG_TEST) {
    597             printf("%016llx %s %016llx ",
    598                    test_val1.u64_val, test_def.op, test_val2.u64_val);
    599          } else {
    600             printf("%016llx %016llx %s %016llx %016llx ",
    601                    test_val1.u128.valu, test_val1.u128.vall, test_def.op, test_val2.u128.valu, test_val2.u128.vall);
    602          }
    603          printf(" => %x (BF=%d)\n", condreg, BF);
    604       }
    605       if (repeat) {
    606          repeat = 0;
    607          BF = 7;
    608          goto again;
    609       }
    610       k++;
    611       printf( "\n" );
    612    }
    613 }
    614 
    615 
    616 static test_table_t
    617          all_tests[] =
    618 {
    619                     { &test_dfp_ExpTest_ops,
    620                       "Test DFP exponent test instructions"},
    621                     { &test_dfp_ClassAndGroupTest_ops,
    622                       "Test DFP class and group test instructions"},
    623                     { NULL, NULL }
    624 };
    625 #endif // HAS_DFP
    626 
    627 int main() {
    628 #if defined(HAS_DFP)
    629 
    630    test_table_t aTest;
    631    test_driver_func_t func;
    632    int i = 0;
    633 
    634    while ((func = all_tests[i].test_category)) {
    635       aTest = all_tests[i];
    636       printf( "%s\n", aTest.name );
    637       (*func)();
    638       i++;
    639    }
    640 
    641 #endif // HAS_DFP
    642    return 0;
    643 }
    644