• 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 #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  */
_test_dtstdc(int BF,int DCM,dfp_val_t * val1,dfp_val_t * x1)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 
_test_dtstdcq(int BF,int DCM,dfp_val_t * val1,dfp_val_t * x1)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  */
_test_dtstdg(int BF,int DGM,dfp_val_t * val1,dfp_val_t * x1)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 
_test_dtstdgq(int BF,int DGM,dfp_val_t * val1,dfp_val_t * x1)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
_test_dtstex(int BF,int x,dfp_val_t * val1,dfp_val_t * val2)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 
_test_dtstexq(int BF,int x,dfp_val_t * val1,dfp_val_t * val2)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 
test_dfp_ClassAndGroupTest_ops(void)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 
test_dfp_ExpTest_ops(void)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 
main()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