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