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