• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*  Copyright (C) 2012 IBM
2 
3  Author: Maynard Johnson <maynardj@us.ibm.com>
4 
5  This program is free software; you can redistribute it and/or
6  modify it under the terms of the GNU General Public License as
7  published by the Free Software Foundation; either version 2 of the
8  License, or (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful, but
11  WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18  02111-1307, USA.
19 
20  The GNU General Public License is contained in the file COPYING.
21  */
22 
23 #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 #ifndef __powerpc64__
83 typedef uint32_t HWord_t;
84 #else
85 typedef uint64_t HWord_t;
86 #endif /* __powerpc64__ */
87 
88 enum BF_vals { BF_val1 = 0, BF_val2 = 1, BF_val3 =6};
89 
90 // The assembly-level instructions being tested
_test_dtstsf(unsigned int BF,unsigned int ref_sig,dfp_val_t valB)91 static void _test_dtstsf(unsigned int BF, unsigned int ref_sig, dfp_val_t valB)
92 {
93    _Decimal64 f16 = valB.dec_val;
94    register HWord_t r14 __asm__ ("r14");
95    double f14;
96    r14 = (HWord_t)&ref_sig;
97 
98    __asm __volatile__ ("lfiwax %0, 0, %1" : "=f" (f14): "r" (r14));
99    switch (BF) {
100       case BF_val1:
101          __asm__ __volatile__ ("dtstsf %0, %1, %2" : : "i" (BF_val1), "f" (f14), "f" (f16));
102          break;
103       case BF_val2:
104          __asm__ __volatile__ ("dtstsf %0, %1, %2" : : "i" (BF_val2), "f" (f14), "f" (f16));
105          break;
106       case BF_val3:
107          __asm__ __volatile__ ("dtstsf %0, %1, %2" : : "i" (BF_val3), "f" (f14), "f" (f16));
108          break;
109       default:
110          fprintf(stderr, "Invalid value %d for BF\n", BF);
111          break;
112    }
113 }
114 
_test_dtstsfq(unsigned int BF,unsigned int ref_sig,dfp_val_t valB)115 static void _test_dtstsfq(unsigned int BF, unsigned int ref_sig, dfp_val_t valB)
116 {
117    _Decimal128 f16 = valB.dec_val128;
118    register HWord_t r14 __asm__ ("r14");
119    double f14;
120    r14 = (HWord_t)&ref_sig;
121 
122    __asm __volatile__ ("lfiwax %0, 0, %1" : "=f" (f14): "r" (r14));
123    switch (BF) {
124       case BF_val1:
125          __asm__ __volatile__ ("dtstsfq %0, %1, %2" : : "i" (BF_val1), "f" (f14), "f" (f16));
126          break;
127       case BF_val2:
128          __asm__ __volatile__ ("dtstsfq %0, %1, %2" : : "i" (BF_val2), "f" (f14), "f" (f16));
129          break;
130       case BF_val3:
131          __asm__ __volatile__ ("dtstsfq %0, %1, %2" : : "i" (BF_val3), "f" (f14), "f" (f16));
132          break;
133       default:
134          fprintf(stderr, "Invalid value %d for BF\n", BF);
135          break;
136    }
137 }
138 
_test_ddedpd(unsigned int SP,dfp_val_t valB)139 static dfp_val_t _test_ddedpd(unsigned int SP, dfp_val_t valB)
140 {
141    _Decimal64 ret = 0;
142    dfp_val_t result;
143    _Decimal64 f16 = valB.dec_val;
144    switch (SP) {
145       case 0:
146          __asm__ __volatile__ ("ddedpd. 0, %0, %1" : "=f" (ret) : "f" (f16));
147          break;
148       case 1:
149          __asm__ __volatile__ ("ddedpd. 1, %0, %1" : "=f" (ret) : "f" (f16));
150          break;
151       case 2:
152          __asm__ __volatile__ ("ddedpd. 2, %0, %1" : "=f" (ret) : "f" (f16));
153          break;
154       case 3:
155          __asm__ __volatile__ ("ddedpd. 3, %0, %1" : "=f" (ret) : "f" (f16));
156          break;
157       default:
158          fprintf(stderr, "Invalid value %d for SP\n", SP);
159          break;
160    }
161    result.dec_val = ret;
162    return result;
163 }
164 
165 
_test_ddedpdq(unsigned int SP,dfp_val_t valB)166 static dfp_val_t _test_ddedpdq(unsigned int SP, dfp_val_t valB)
167 {
168    _Decimal128 ret = 0;
169    dfp_val_t result;
170    _Decimal128 f16 = valB.dec_val128;
171    switch (SP) {
172       case 0:
173          __asm__ __volatile__ ("ddedpdq 0, %0, %1" : "=f" (ret) : "f" (f16));
174          break;
175       case 1:
176          __asm__ __volatile__ ("ddedpdq 1, %0, %1" : "=f" (ret) : "f" (f16));
177          break;
178       case 2:
179          __asm__ __volatile__ ("ddedpdq 2, %0, %1" : "=f" (ret) : "f" (f16));
180          break;
181       case 3:
182          __asm__ __volatile__ ("ddedpdq 3, %0, %1" : "=f" (ret) : "f" (f16));
183          break;
184       default:
185          fprintf(stderr, "Invalid value %d for SP\n", SP);
186          break;
187    }
188    result.dec_val128 = ret;
189    return result;
190 }
191 
_test_denbcd(unsigned int S,dfp_val_t valB)192 static dfp_val_t _test_denbcd(unsigned int S, dfp_val_t valB)
193 {
194    _Decimal64 ret = 0;
195    dfp_val_t result;
196    _Decimal64 f16 = valB.dec_val;
197    switch (S) {
198       case 0:
199          __asm__ __volatile__ ("denbcd. 0, %0, %1" : "=f" (ret) : "f" (f16));
200          break;
201       case 1:
202          __asm__ __volatile__ ("denbcd. 1, %0, %1" : "=f" (ret) : "f" (f16));
203          break;
204       default:
205          fprintf(stderr, "Invalid value %d for S\n", S);
206          break;
207    }
208    result.dec_val = ret;
209    return result;
210 }
211 
212 
_test_denbcdq(unsigned int S,dfp_val_t valB)213 static dfp_val_t _test_denbcdq(unsigned int S, dfp_val_t valB)
214 {
215    _Decimal128 ret = 0;
216    dfp_val_t result;
217    _Decimal128 f16 = valB.dec_val128;
218    switch (S) {
219       case 0:
220          __asm__ __volatile__ ("denbcdq 0, %0, %1" : "=f" (ret) : "f" (f16));
221          break;
222       case 1:
223          __asm__ __volatile__ ("denbcdq 1, %0, %1" : "=f" (ret) : "f" (f16));
224          break;
225       default:
226          fprintf(stderr, "Invalid value %d for S\n", S);
227          break;
228    }
229    result.dec_val128 = ret;
230    return result;
231 }
232 
233 
234 typedef void (*test_func_t)(unsigned int imm, unsigned int imm2,  dfp_val_t valB);
235 typedef dfp_val_t (*test_func_bcd_t)(unsigned int imm, dfp_val_t valB);
236 typedef void (*test_driver_func_t)(void);
237 typedef struct test_table
238 {
239    test_driver_func_t test_category;
240    char * name;
241 } test_table_t;
242 
243 /*
244  *  345.0DD (0x2207c00000000000 0xe50)
245  *  1.2300e+5DD (0x2207c00000000000 0x14c000)
246  *  -16.0DD (0xa207c00000000000 0xe0)
247  *  0.00189DD (0x2206c00000000000 0xcf)
248  *  -4.1235DD (0xa205c00000000000 0x10a395bcf)
249  *  9.8399e+20DD (0x2209400000000000 0x253f1f534acdd4)
250  *  0DD (0x2208000000000000 0x0)
251  *  0DD (0x2208000000000000 0x0)
252  *  infDD (0x7800000000000000 0x0)
253  *  nanDD (0x7c00000000000000 0x0
254  */
255 static unsigned long long dfp128_vals[] = {
256                                     // Some finite numbers
257                                     0x2207c00000000000ULL, 0x0000000000000e50ULL,
258                                     0x2207c00000000000ULL, 0x000000000014c000ULL,
259                                     0xa207c00000000000ULL, 0x00000000000000e0ULL,
260                                     0x2206c00000000000ULL, 0x00000000000000cfULL,
261                                     0xa205c00000000000ULL, 0x000000010a395bcfULL,
262                                     0x6209400000fd0000ULL, 0x00253f1f534acdd4ULL, // huge number
263                                     0x000400000089b000ULL, 0x0a6000d000000049ULL, // very small number
264                                     // flavors of zero
265                                     0x2208000000000000ULL, 0x0000000000000000ULL,
266                                     0xa208000000000000ULL, 0x0000000000000000ULL, // negative
267                                     0xa248000000000000ULL, 0x0000000000000000ULL,
268                                     // flavors of NAN
269                                     0x7c00000000000000ULL, 0x0000000000000000ULL, // quiet
270                                     0xfc00000000000000ULL, 0xc00100035b007700ULL,
271                                     0x7e00000000000000ULL, 0xfe000000d0e0a0d0ULL, // signaling
272                                     // flavors of Infinity
273                                     0x7800000000000000ULL, 0x0000000000000000ULL,
274                                     0xf800000000000000ULL, 0x0000000000000000ULL, // negative
275                                     0xf900000000000000ULL, 0x0000000000000000ULL
276 };
277 
278 static unsigned long long dfp64_vals[] = {
279                                  // various finite numbers
280                                  0x2234000000000e50ULL,
281                                  0x223400000014c000ULL,
282                                  0xa2340000000000e0ULL,// negative
283                                  0x22240000000000cfULL,
284                                  0xa21400010a395bcfULL,// negative
285                                  0x6e4d3f1f534acdd4ULL,// huge number
286                                  0x000400000089b000ULL,// very small number
287                                  // flavors of zero
288                                  0x2238000000000000ULL,
289                                  0xa238000000000000ULL,
290                                  0x4248000000000000ULL,
291                                  // flavors of NAN
292                                  0x7e34000000000111ULL,
293                                  0xfe000000d0e0a0d0ULL,//signaling
294                                  0xfc00000000000000ULL,//quiet
295                                  // flavors of Infinity
296                                  0x7800000000000000ULL,
297                                  0xf800000000000000ULL,//negative
298                                  0x7a34000000000000ULL,
299 };
300 
301 /* The bcd64_vals and bdc128_vals hold the unique results of executing
302  * the ddedpd instruction on the basic dfp64 and dfp128 array values.
303  * Executing the inverse operation (denbcd) on these values with the
304  * appropriate S (signed) value should yield values approximating the
305  * original dfp values (except being 2^4 in magnitude since the decoding
306  * operation shifted the value one hex digit to the left to make room
307  * for signedness info).
308  */
309 static unsigned long long bcd64_vals[] = {
310                                           0x0000000000003450ULL,
311                                           0x000000000003450cULL,
312                                           0x000000000003450fULL,
313                                           0x0000000001230000ULL,
314                                           0x000000001230000cULL,
315                                           0x000000001230000fULL,
316                                           0x0000000000000160ULL,
317                                           0x000000000000160dULL,
318                                           0x0000000000000189ULL,
319                                           0x000000000000189cULL,
320                                           0x000000000000189fULL,
321                                           0x0000004123456789ULL,
322                                           0x000004123456789dULL,
323                                           0x9839871234533354ULL,
324                                           0x839871234533354cULL,
325                                           0x839871234533354fULL,
326                                           0x0000000008864000ULL,
327                                           0x000000008864000cULL,
328                                           0x000000008864000fULL,
329                                           0x0000000000000000ULL,
330                                           0x000000000000000cULL,
331                                           0x000000000000000fULL,
332                                           0x000000000000000dULL,
333                                           0x0000000000000211ULL,
334                                           0x000000000000211cULL,
335                                           0x000000000000211fULL,
336                                           0x0000003882028150ULL,
337                                           0x000003882028150dULL
338  };
339 
340 static unsigned long long bcd128_vals[] = {
341                                            0x0000000000000000ULL, 0x0000000000003450ULL,
342                                            0x0000000000000000ULL, 0x000000000003450cULL,
343                                            0x0000000000000000ULL, 0x000000000003450fULL,
344                                            0x0000000000000000ULL, 0x0000000001230000ULL,
345                                            0x0000000000000000ULL, 0x000000001230000cULL,
346                                            0x0000000000000000ULL, 0x000000001230000fULL,
347                                            0x0000000000000000ULL, 0x0000000000000160ULL,
348                                            0x0000000000000000ULL, 0x000000000000160dULL,
349                                            0x0000000000000000ULL, 0x0000000000000189ULL,
350                                            0x0000000000000000ULL, 0x000000000000189cULL,
351                                            0x0000000000000000ULL, 0x000000000000189fULL,
352                                            0x0000000000000000ULL, 0x0000004123456789ULL,
353                                            0x0000000000000000ULL, 0x000004123456789dULL,
354                                            0x0000097100000000ULL, 0x9839871234533354ULL,
355                                            0x0000971000000009ULL, 0x839871234533354cULL,
356                                            0x0000971000000009ULL, 0x839871234533354fULL,
357                                            0x0000010954000051ULL, 0x8000640000000049ULL,
358                                            0x0000109540000518ULL, 0x000640000000049cULL,
359                                            0x0000109540000518ULL, 0x000640000000049fULL,
360                                            0x0000000000000000ULL, 0x0000000000000000ULL,
361                                            0x0000000000000000ULL, 0x000000000000000cULL,
362                                            0x0000000000000000ULL, 0x000000000000000fULL,
363                                            0x0000000000000000ULL, 0x000000000000000dULL,
364                                            0x0000000000080000ULL, 0x0200801330811600ULL,
365                                            0x0000000000800000ULL, 0x200801330811600dULL,
366                                            0x0000000000088170ULL, 0x0000003882028150ULL,
367                                            0x0000000000881700ULL, 0x000003882028150cULL,
368                                            0x0000000000881700ULL, 0x000003882028150fULL
369 };
370 
371 // Both Long and Quad arrays of DFP values should have the same length, so it
372 // doesn't matter which array I use for calculating the following #define.
373 #define NUM_DFP_VALS (sizeof(dfp64_vals)/8)
374 
375 typedef enum {
376    LONG_TEST,
377    QUAD_TEST
378 } precision_type_t;
379 
380 typedef struct dfp_one_arg_test
381 {
382    test_func_t test_func;
383    const char * name;
384    precision_type_t precision;
385    const char * op;
386 } dfp_one_arg_test_t;
387 
388 typedef struct dfp_one_arg_bcd_test
389 {
390    test_func_bcd_t test_func;
391    const char * name;
392    precision_type_t precision;
393    const char * op;
394 } dfp_one_arg_bcd_test_t;
395 
396 static dfp_one_arg_bcd_test_t
397 dfp_test_dfp_ddedpd_tests[] = {
398                             { &_test_ddedpd, "ddedpd", LONG_TEST, "[D->B]"},
399                             { &_test_ddedpdq, "ddedpdq", QUAD_TEST, "[D->B]"},
400                             { NULL, NULL, 0, NULL}
401 };
402 
test_dfp_ddedpd_ops(void)403 static void test_dfp_ddedpd_ops(void)
404 {
405    test_func_bcd_t func;
406    dfp_val_t test_val;
407 
408    int k = 0;
409 
410    while ((func = dfp_test_dfp_ddedpd_tests[k].test_func)) {
411       int i;
412       dfp_one_arg_bcd_test_t test_def = dfp_test_dfp_ddedpd_tests[k];
413 
414       for (i = 0; i < NUM_DFP_VALS; i++) {
415          unsigned int SP;
416 
417          if (test_def.precision == LONG_TEST) {
418             test_val.u64_val = dfp64_vals[i];
419          } else {
420             test_val.u128.valu = dfp128_vals[i * 2];
421             test_val.u64_val = test_val.u128.valu;
422             test_val.u128.vall = dfp128_vals[(i * 2) + 1];
423          }
424 
425          for (SP = 0; SP < 4; SP++) {
426             dfp_val_t result;
427             result = (*func)(SP, test_val);
428             printf("%s (SP=%d) %s%016llx", test_def.name, SP,
429                    test_def.op, test_val.u64_val);
430             if (test_def.precision == QUAD_TEST) {
431                printf(" %016llx", test_val.u128.vall);
432             }
433             if (test_def.precision == LONG_TEST)
434                printf(" ==> %016llx\n", result.u64_val);
435             else
436                printf(" ==> %016llx %016llx\n", result.u128.valu, result.u128.vall);
437          }
438       }
439       k++;
440       printf( "\n" );
441    }
442 }
443 
444 static dfp_one_arg_bcd_test_t
445 dfp_test_dfp_denbcd_tests[] = {
446                             { &_test_denbcd, "denbcd", LONG_TEST, "[B->D]"},
447                             { &_test_denbcdq, "denbcdq", QUAD_TEST, "[B->D]"},
448                             { NULL, NULL, 0, NULL}
449 };
450 
test_dfp_denbcd_ops(void)451 static void test_dfp_denbcd_ops(void)
452 {
453    test_func_bcd_t func;
454    dfp_val_t test_val;
455    int num_test_vals;
456 
457    int k = 0;
458 
459    while ((func = dfp_test_dfp_denbcd_tests[k].test_func)) {
460       int i;
461       dfp_one_arg_bcd_test_t test_def = dfp_test_dfp_denbcd_tests[k];
462       if (test_def.precision == LONG_TEST)
463          num_test_vals = sizeof(bcd64_vals)/sizeof(unsigned long long);
464       else
465          num_test_vals = sizeof(bcd128_vals)/(2 * sizeof(unsigned long long));
466 
467       for (i = 0; i < num_test_vals; i++) {
468          unsigned int S;
469          dfp_val_t result;
470          /* The DPD-to-BCD decodings may contain up to 3 decodings for each normal DFP
471           * value: the first is an unsigned decoding, and the other two are
472           * signed decodings, with SP[1] set to '0' and '1' respectively at decode
473           * time. But some of the results of decodings were duplicates, so they were
474           * not included in the bcd64_vals and bcd128_vals arrays.
475           *
476           * When doing the encoding operation (denbcd), we'll attempt both S=0 and
477           * S=1; one or the other should encode the BCD value to something close to
478           * its original DFP value (except being 2^4 in magnitude since the decoding
479           * operation shifted the value one hex digit to the left to make room
480           * for signedness info).
481           */
482          for (S = 0; S < 2; S++) {
483             if (test_def.precision == LONG_TEST) {
484                test_val.u64_val = bcd64_vals[i];
485             } else {
486                test_val.u128.valu = bcd128_vals[i * 2];
487                test_val.u64_val = test_val.u128.valu;
488                test_val.u128.vall = bcd128_vals[(i * 2) + 1];
489             }
490 
491             result = (*func)(S, test_val);
492             printf("%s (S=%d) %s%016llx", test_def.name, S,
493                    test_def.op, test_val.u64_val);
494             if (test_def.precision == QUAD_TEST) {
495                printf(" %016llx", test_val.u128.vall);
496             }
497             if (test_def.precision == LONG_TEST)
498                printf(" ==> %016llx\n", result.u64_val);
499             else
500                printf(" ==> %016llx %016llx\n", result.u128.valu, result.u128.vall);
501          }
502       }
503       k++;
504       printf( "\n" );
505    }
506 }
507 
508 
509 static dfp_one_arg_test_t
510 dfp_test_significance_tests[] = {
511                                           { &_test_dtstsf,  "dtstsf", LONG_TEST, "[tSig]"},
512                                           { &_test_dtstsfq, "dtstsfq", QUAD_TEST, "[tSig]"},
513                                           { NULL, NULL, 0, NULL}
514 };
515 
test_dfp_test_significance_ops(void)516 static void test_dfp_test_significance_ops(void)
517 {
518    test_func_t func;
519    dfp_val_t test_valB;
520    int k = 0;
521    unsigned int BF_vals[] = {BF_val1, BF_val2, BF_val3};
522    unsigned int reference_sig, reference_sig_vals[] = {0U, 1U, 2U, 4U, 6U, 63U};
523    int num_reference_sig_vals = sizeof(reference_sig_vals)/sizeof(unsigned int);
524 
525    while ((func = dfp_test_significance_tests[k].test_func)) {
526       int i;
527       dfp_one_arg_test_t test_def = dfp_test_significance_tests[k];
528 
529       for (i = 0; i < NUM_DFP_VALS; i++) {
530          int j;
531          if (test_def.precision == LONG_TEST) {
532             test_valB.u64_val = dfp64_vals[i];
533          } else {
534             test_valB.u128.valu = dfp128_vals[i * 2];
535             test_valB.u64_val = test_valB.u128.valu;
536             test_valB.u128.vall = dfp128_vals[(i * 2) + 1];
537          }
538 
539          for (j = 0; j < num_reference_sig_vals; j++) {
540             int bf_idx, BF;
541             reference_sig = reference_sig_vals[j];
542             for (bf_idx = 0; bf_idx < sizeof(BF_vals)/sizeof(unsigned int); bf_idx++) {
543                unsigned int condreg;
544                unsigned int flags;
545                BF = BF_vals[bf_idx];
546                SET_FPSCR_ZERO;
547                SET_CR_XER_ZERO;
548                (*func)(BF, reference_sig, test_valB);
549                GET_CR(flags);
550 
551                condreg = ((flags >> (4 * (7-BF)))) & 0xf;
552                printf("%s (ref_sig=%d) %s%016llx", test_def.name, reference_sig,
553                       test_def.op, test_valB.u64_val);
554                if (test_def.precision == QUAD_TEST) {
555                   printf(" %016llx", test_valB.u128.vall);
556                }
557                printf(" => %x (BF=%d)\n", condreg, BF);
558             }
559          }
560          printf( "\n" );
561       }
562       k++;
563    }
564 }
565 
566 static test_table_t
567          all_tests[] =
568 {
569                     { &test_dfp_test_significance_ops,
570                       "Test DFP test significance instructions"},
571                     { &test_dfp_ddedpd_ops,
572                       "Test DFP DPD-to-BCD instructions"},
573                     { &test_dfp_denbcd_ops,
574                       "Test DFP BCD-to-DPD instructions"},
575                     { NULL, NULL }
576 };
577 #endif // HAS_DFP
578 
main()579 int main() {
580 #if defined(HAS_DFP)
581 
582    test_table_t aTest;
583    test_driver_func_t func;
584    int i = 0;
585 
586    while ((func = all_tests[i].test_category)) {
587       aTest = all_tests[i];
588       printf( "%s\n", aTest.name );
589       (*func)();
590       i++;
591    }
592 
593 #endif // HAS_DFP
594    return 0;
595 }
596