1 /* Copyright (C) 2012 IBM
3 Author: Maynard Johnson <maynardj@us.ibm.com>
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.
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.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, see <http://www.gnu.org/licenses/>.
18 The GNU General Public License is contained in the file COPYING.
29 _Decimal128 dec_val128
;
30 unsigned long long u64_val
;
32 #if defined(VGP_ppc64le_linux)
33 unsigned long long vall
;
34 unsigned long long valu
;
36 unsigned long long valu
;
37 unsigned long long vall
;
43 typedef unsigned char Bool
;
48 #define ALLCR "cr0","cr1","cr2","cr3","cr4","cr5","cr6","cr7"
50 #define SET_CR(_arg) \
51 __asm__ __volatile__ ("mtcr %0" : : "b"(_arg) : ALLCR );
53 #define SET_XER(_arg) \
54 __asm__ __volatile__ ("mtxer %0" : : "b"(_arg) : "xer" );
56 #define GET_CR(_lval) \
57 __asm__ __volatile__ ("mfcr %0" : "=b"(_lval) )
59 #define GET_XER(_lval) \
60 __asm__ __volatile__ ("mfxer %0" : "=b"(_lval) )
62 #define GET_CR_XER(_lval_cr,_lval_xer) \
63 do { GET_CR(_lval_cr); GET_XER(_lval_xer); } while (0)
68 #define SET_XER_ZERO \
71 #define SET_CR_XER_ZERO \
72 do { SET_CR_ZERO; SET_XER_ZERO; } while (0)
74 #define SET_FPSCR_ZERO \
75 do { double _d = 0.0; \
76 __asm__ __volatile__ ("mtfsf 0xFF, %0" : : "f"(_d) ); \
79 #define GET_FPSCR(_arg) \
80 __asm__ __volatile__ ("mffs %0" : "=f"(_arg) )
82 #define SET_FPSCR_DRN \
83 __asm__ __volatile__ ("mtfsf 1, %0, 0, 1" : : "f"(f14) )
86 typedef uint32_t HWord_t
;
88 typedef uint64_t HWord_t
;
89 #endif /* __powerpc64__ */
91 enum BF_vals
{ BF_val1
= 0, BF_val2
= 1, BF_val3
=6};
93 // The assembly-level instructions being tested
94 static void _test_dtstsf(unsigned int BF
, unsigned int ref_sig
, dfp_val_t
*valB
)
96 _Decimal64 f16
= valB
->dec_val
;
97 register HWord_t r14
__asm__ ("r14");
99 r14
= (HWord_t
)&ref_sig
;
101 __asm
__volatile__ ("lfiwax %0, 0, %1" : "=f" (f14
): "r" (r14
));
104 __asm__
__volatile__ ("dtstsf %0, %1, %2" : : "i" (BF_val1
), "f" (f14
), "f" (f16
));
107 __asm__
__volatile__ ("dtstsf %0, %1, %2" : : "i" (BF_val2
), "f" (f14
), "f" (f16
));
110 __asm__
__volatile__ ("dtstsf %0, %1, %2" : : "i" (BF_val3
), "f" (f14
), "f" (f16
));
113 fprintf(stderr
, "Invalid value %d for BF\n", BF
);
118 static void _test_dtstsfq(unsigned int BF
, unsigned int ref_sig
, dfp_val_t
*valB
)
120 _Decimal128 f16
= valB
->dec_val128
;
121 register HWord_t r14
__asm__ ("r14");
123 r14
= (HWord_t
)&ref_sig
;
125 __asm
__volatile__ ("lfiwax %0, 0, %1" : "=f" (f14
): "r" (r14
));
128 __asm__
__volatile__ ("dtstsfq %0, %1, %2" : : "i" (BF_val1
), "f" (f14
), "f" (f16
));
131 __asm__
__volatile__ ("dtstsfq %0, %1, %2" : : "i" (BF_val2
), "f" (f14
), "f" (f16
));
134 __asm__
__volatile__ ("dtstsfq %0, %1, %2" : : "i" (BF_val3
), "f" (f14
), "f" (f16
));
137 fprintf(stderr
, "Invalid value %d for BF\n", BF
);
142 static dfp_val_t
_test_ddedpd(unsigned int SP
, dfp_val_t
*valB
)
146 _Decimal64 f16
= valB
->dec_val
;
149 __asm__
__volatile__ ("ddedpd. 0, %0, %1" : "=f" (ret
) : "f" (f16
));
152 __asm__
__volatile__ ("ddedpd. 1, %0, %1" : "=f" (ret
) : "f" (f16
));
155 __asm__
__volatile__ ("ddedpd. 2, %0, %1" : "=f" (ret
) : "f" (f16
));
158 __asm__
__volatile__ ("ddedpd. 3, %0, %1" : "=f" (ret
) : "f" (f16
));
161 fprintf(stderr
, "Invalid value %d for SP\n", SP
);
164 result
.dec_val
= ret
;
169 static dfp_val_t
_test_ddedpdq(unsigned int SP
, dfp_val_t
*valB
)
173 _Decimal128 f16
= valB
->dec_val128
;
176 __asm__
__volatile__ ("ddedpdq 0, %0, %1" : "=f" (ret
) : "f" (f16
));
179 __asm__
__volatile__ ("ddedpdq 1, %0, %1" : "=f" (ret
) : "f" (f16
));
182 __asm__
__volatile__ ("ddedpdq 2, %0, %1" : "=f" (ret
) : "f" (f16
));
185 __asm__
__volatile__ ("ddedpdq 3, %0, %1" : "=f" (ret
) : "f" (f16
));
188 fprintf(stderr
, "Invalid value %d for SP\n", SP
);
191 result
.dec_val128
= ret
;
195 static dfp_val_t
_test_denbcd(unsigned int S
, dfp_val_t
*valB
)
199 _Decimal64 f16
= valB
->dec_val
;
202 __asm__
__volatile__ ("denbcd. 0, %0, %1" : "=f" (ret
) : "f" (f16
));
205 __asm__
__volatile__ ("denbcd. 1, %0, %1" : "=f" (ret
) : "f" (f16
));
208 fprintf(stderr
, "Invalid value %d for S\n", S
);
211 result
.dec_val
= ret
;
216 static dfp_val_t
_test_denbcdq(unsigned int S
, dfp_val_t
*valB
)
220 _Decimal128 f16
= valB
->dec_val128
;
223 __asm__
__volatile__ ("denbcdq 0, %0, %1" : "=f" (ret
) : "f" (f16
));
226 __asm__
__volatile__ ("denbcdq 1, %0, %1" : "=f" (ret
) : "f" (f16
));
229 fprintf(stderr
, "Invalid value %d for S\n", S
);
232 result
.dec_val128
= ret
;
237 typedef void (*test_funcp_t
)(unsigned int imm
, unsigned int imm2
, dfp_val_t
*valB
);
238 typedef dfp_val_t (*test_func_bcdp_t
)(unsigned int imm
, dfp_val_t
*valB
);
239 typedef void (*test_driver_func_t
)(void);
240 typedef struct test_table
242 test_driver_func_t test_category
;
247 * 345.0DD (0x2207c00000000000 0xe50)
248 * 1.2300e+5DD (0x2207c00000000000 0x14c000)
249 * -16.0DD (0xa207c00000000000 0xe0)
250 * 0.00189DD (0x2206c00000000000 0xcf)
251 * -4.1235DD (0xa205c00000000000 0x10a395bcf)
252 * 9.8399e+20DD (0x2209400000000000 0x253f1f534acdd4)
253 * 0DD (0x2208000000000000 0x0)
254 * 0DD (0x2208000000000000 0x0)
255 * infDD (0x7800000000000000 0x0)
256 * nanDD (0x7c00000000000000 0x0
258 static unsigned long long dfp128_vals
[] = {
259 // Some finite numbers
260 0x2207c00000000000ULL
, 0x0000000000000e50ULL
,
261 0x2207c00000000000ULL
, 0x000000000014c000ULL
,
262 0xa207c00000000000ULL
, 0x00000000000000e0ULL
,
263 0x2206c00000000000ULL
, 0x00000000000000cfULL
,
264 0xa205c00000000000ULL
, 0x000000010a395bcfULL
,
265 0x6209400000fd0000ULL
, 0x00253f1f534acdd4ULL
, // huge number
266 0x000400000089b000ULL
, 0x0a6000d000000049ULL
, // very small number
268 0x2208000000000000ULL
, 0x0000000000000000ULL
,
269 0xa208000000000000ULL
, 0x0000000000000000ULL
, // negative
270 0xa248000000000000ULL
, 0x0000000000000000ULL
,
272 0x7c00000000000000ULL
, 0x0000000000000000ULL
, // quiet
273 0xfc00000000000000ULL
, 0xc00100035b007700ULL
,
274 0x7e00000000000000ULL
, 0xfe000000d0e0a0d0ULL
, // signaling
275 // flavors of Infinity
276 0x7800000000000000ULL
, 0x0000000000000000ULL
,
277 0xf800000000000000ULL
, 0x0000000000000000ULL
, // negative
278 0xf900000000000000ULL
, 0x0000000000000000ULL
281 static unsigned long long dfp64_vals
[] = {
282 // various finite numbers
283 0x2234000000000e50ULL
,
284 0x223400000014c000ULL
,
285 0xa2340000000000e0ULL
,// negative
286 0x22240000000000cfULL
,
287 0xa21400010a395bcfULL
,// negative
288 0x6e4d3f1f534acdd4ULL
,// huge number
289 0x000400000089b000ULL
,// very small number
291 0x2238000000000000ULL
,
292 0xa238000000000000ULL
,
293 0x4248000000000000ULL
,
295 0x7e34000000000111ULL
,
296 0xfe000000d0e0a0d0ULL
,//signaling
297 0xfc00000000000000ULL
,//quiet
298 // flavors of Infinity
299 0x7800000000000000ULL
,
300 0xf800000000000000ULL
,//negative
301 0x7a34000000000000ULL
,
304 /* The bcd64_vals and bdc128_vals hold the unique results of executing
305 * the ddedpd instruction on the basic dfp64 and dfp128 array values.
306 * Executing the inverse operation (denbcd) on these values with the
307 * appropriate S (signed) value should yield values approximating the
308 * original dfp values (except being 2^4 in magnitude since the decoding
309 * operation shifted the value one hex digit to the left to make room
310 * for signedness info).
312 static unsigned long long bcd64_vals
[] = {
313 0x0000000000003450ULL
,
314 0x000000000003450cULL
,
315 0x000000000003450fULL
,
316 0x0000000001230000ULL
,
317 0x000000001230000cULL
,
318 0x000000001230000fULL
,
319 0x0000000000000160ULL
,
320 0x000000000000160dULL
,
321 0x0000000000000189ULL
,
322 0x000000000000189cULL
,
323 0x000000000000189fULL
,
324 0x0000004123456789ULL
,
325 0x000004123456789dULL
,
326 0x9839871234533354ULL
,
327 0x839871234533354cULL
,
328 0x839871234533354fULL
,
329 0x0000000008864000ULL
,
330 0x000000008864000cULL
,
331 0x000000008864000fULL
,
332 0x0000000000000000ULL
,
333 0x000000000000000cULL
,
334 0x000000000000000fULL
,
335 0x000000000000000dULL
,
336 0x0000000000000211ULL
,
337 0x000000000000211cULL
,
338 0x000000000000211fULL
,
339 0x0000003882028150ULL
,
340 0x000003882028150dULL
343 static unsigned long long bcd128_vals
[] = {
344 0x0000000000000000ULL
, 0x0000000000003450ULL
,
345 0x0000000000000000ULL
, 0x000000000003450cULL
,
346 0x0000000000000000ULL
, 0x000000000003450fULL
,
347 0x0000000000000000ULL
, 0x0000000001230000ULL
,
348 0x0000000000000000ULL
, 0x000000001230000cULL
,
349 0x0000000000000000ULL
, 0x000000001230000fULL
,
350 0x0000000000000000ULL
, 0x0000000000000160ULL
,
351 0x0000000000000000ULL
, 0x000000000000160dULL
,
352 0x0000000000000000ULL
, 0x0000000000000189ULL
,
353 0x0000000000000000ULL
, 0x000000000000189cULL
,
354 0x0000000000000000ULL
, 0x000000000000189fULL
,
355 0x0000000000000000ULL
, 0x0000004123456789ULL
,
356 0x0000000000000000ULL
, 0x000004123456789dULL
,
357 0x0000097100000000ULL
, 0x9839871234533354ULL
,
358 0x0000971000000009ULL
, 0x839871234533354cULL
,
359 0x0000971000000009ULL
, 0x839871234533354fULL
,
360 0x0000010954000051ULL
, 0x8000640000000049ULL
,
361 0x0000109540000518ULL
, 0x000640000000049cULL
,
362 0x0000109540000518ULL
, 0x000640000000049fULL
,
363 0x0000000000000000ULL
, 0x0000000000000000ULL
,
364 0x0000000000000000ULL
, 0x000000000000000cULL
,
365 0x0000000000000000ULL
, 0x000000000000000fULL
,
366 0x0000000000000000ULL
, 0x000000000000000dULL
,
367 0x0000000000080000ULL
, 0x0200801330811600ULL
,
368 0x0000000000800000ULL
, 0x200801330811600dULL
,
369 0x0000000000088170ULL
, 0x0000003882028150ULL
,
370 0x0000000000881700ULL
, 0x000003882028150cULL
,
371 0x0000000000881700ULL
, 0x000003882028150fULL
374 // Both Long and Quad arrays of DFP values should have the same length, so it
375 // doesn't matter which array I use for calculating the following #define.
376 #define NUM_DFP_VALS (sizeof(dfp64_vals)/8)
383 typedef struct dfp_one_arg_test
385 test_funcp_t test_func
;
387 precision_type_t precision
;
389 } dfp_one_arg_test_t
;
391 typedef struct dfp_one_arg_bcd_test
393 test_func_bcdp_t test_func
;
395 precision_type_t precision
;
397 } dfp_one_arg_bcd_test_t
;
399 static dfp_one_arg_bcd_test_t
400 dfp_test_dfp_ddedpd_tests
[] = {
401 { &_test_ddedpd
, "ddedpd", LONG_TEST
, "[D->B]"},
402 { &_test_ddedpdq
, "ddedpdq", QUAD_TEST
, "[D->B]"},
403 { NULL
, NULL
, 0, NULL
}
406 static void test_dfp_ddedpd_ops(void)
408 test_func_bcdp_t func
;
413 while ((func
= dfp_test_dfp_ddedpd_tests
[k
].test_func
)) {
415 dfp_one_arg_bcd_test_t test_def
= dfp_test_dfp_ddedpd_tests
[k
];
417 for (i
= 0; i
< NUM_DFP_VALS
; i
++) {
420 if (test_def
.precision
== LONG_TEST
) {
421 test_val
.u64_val
= dfp64_vals
[i
];
423 test_val
.u128
.valu
= dfp128_vals
[i
* 2];
424 test_val
.u128
.vall
= dfp128_vals
[(i
* 2) + 1];
427 for (SP
= 0; SP
< 4; SP
++) {
430 /* There is an ABI change in how 128 bit arguments are aligned
431 * with GCC 5.0. The compiler generates a "note" about this
432 * starting with GCC 4.8. To avoid generating the "note", pass
433 * the address of the 128-bit arguments rather then the value.
435 result
= (*func
)(SP
, &test_val
);
436 printf("%s (SP=%d) %s", test_def
.name
, SP
, test_def
.op
);
437 if (test_def
.precision
== LONG_TEST
) {
438 printf("%016llx ==> %016llx\n", test_val
.u64_val
, result
.u64_val
);
440 printf("%016llx %016llx ==> %016llx %016llx\n",
441 test_val
.u128
.valu
, test_val
.u128
.vall
,
442 result
.u128
.valu
, result
.u128
.vall
);
451 static dfp_one_arg_bcd_test_t
452 dfp_test_dfp_denbcd_tests
[] = {
453 { &_test_denbcd
, "denbcd", LONG_TEST
, "[B->D]"},
454 { &_test_denbcdq
, "denbcdq", QUAD_TEST
, "[B->D]"},
455 { NULL
, NULL
, 0, NULL
}
458 static void test_dfp_denbcd_ops(void)
460 test_func_bcdp_t func
;
466 while ((func
= dfp_test_dfp_denbcd_tests
[k
].test_func
)) {
468 dfp_one_arg_bcd_test_t test_def
= dfp_test_dfp_denbcd_tests
[k
];
469 if (test_def
.precision
== LONG_TEST
)
470 num_test_vals
= sizeof(bcd64_vals
)/sizeof(unsigned long long);
472 num_test_vals
= sizeof(bcd128_vals
)/(2 * sizeof(unsigned long long));
474 for (i
= 0; i
< num_test_vals
; i
++) {
477 /* The DPD-to-BCD decodings may contain up to 3 decodings for each normal DFP
478 * value: the first is an unsigned decoding, and the other two are
479 * signed decodings, with SP[1] set to '0' and '1' respectively at decode
480 * time. But some of the results of decodings were duplicates, so they were
481 * not included in the bcd64_vals and bcd128_vals arrays.
483 * When doing the encoding operation (denbcd), we'll attempt both S=0 and
484 * S=1; one or the other should encode the BCD value to something close to
485 * its original DFP value (except being 2^4 in magnitude since the decoding
486 * operation shifted the value one hex digit to the left to make room
487 * for signedness info).
489 for (S
= 0; S
< 2; S
++) {
490 if (test_def
.precision
== LONG_TEST
) {
491 test_val
.u64_val
= bcd64_vals
[i
];
493 test_val
.u128
.valu
= bcd128_vals
[i
* 2];
494 test_val
.u128
.vall
= bcd128_vals
[(i
* 2) + 1];
497 /* There is an API change in how 128 bit arguments are aligned
498 * with GCC 5.0. The compiler generates a "note" about this
499 * starting with GCC 4.8. To avoid generating the "note", pass
500 * the address of the 128-bit arguments rather then the value.
502 result
= (*func
)(S
, &test_val
);
503 printf("%s (S=%d) %s", test_def
.name
, S
, test_def
.op
);
504 if (test_def
.precision
== LONG_TEST
) {
505 printf("%016llx ==> %016llx\n", test_val
.u64_val
, result
.u64_val
);
507 printf("%016llx %016llx ==> %016llx %016llx\n",
508 test_val
.u128
.valu
, test_val
.u128
.vall
,
509 result
.u128
.valu
, result
.u128
.vall
);
519 static dfp_one_arg_test_t
520 dfp_test_significance_tests
[] = {
521 { &_test_dtstsf
, "dtstsf", LONG_TEST
, "[tSig]"},
522 { &_test_dtstsfq
, "dtstsfq", QUAD_TEST
, "[tSig]"},
523 { NULL
, NULL
, 0, NULL
}
526 static void test_dfp_test_significance_ops(void)
531 unsigned int BF_vals
[] = {BF_val1
, BF_val2
, BF_val3
};
532 unsigned int reference_sig
, reference_sig_vals
[] = {0U, 1U, 2U, 4U, 6U, 63U};
533 int num_reference_sig_vals
= sizeof(reference_sig_vals
)/sizeof(unsigned int);
535 while ((func
= dfp_test_significance_tests
[k
].test_func
)) {
537 dfp_one_arg_test_t test_def
= dfp_test_significance_tests
[k
];
539 for (i
= 0; i
< NUM_DFP_VALS
; i
++) {
541 if (test_def
.precision
== LONG_TEST
) {
542 test_valB
.u64_val
= dfp64_vals
[i
];
544 test_valB
.u128
.valu
= dfp128_vals
[i
* 2];
545 test_valB
.u128
.vall
= dfp128_vals
[(i
* 2) + 1];
548 for (j
= 0; j
< num_reference_sig_vals
; j
++) {
550 reference_sig
= reference_sig_vals
[j
];
551 for (bf_idx
= 0; bf_idx
< sizeof(BF_vals
)/sizeof(unsigned int); bf_idx
++) {
552 unsigned int condreg
;
554 BF
= BF_vals
[bf_idx
];
557 /* There is an ABI change in how 128 bit arguments are aligned
558 * with GCC 5.0. The compiler generates a "note" about this
559 * starting with GCC 4.9. To avoid generating the "note", pass
560 * the address of the 128-bit arguments rather then the value.
562 (*func
)(BF
, reference_sig
, &test_valB
);
565 condreg
= ((flags
>> (4 * (7-BF
)))) & 0xf;
566 printf("%s (ref_sig=%d) %s", test_def
.name
, reference_sig
, test_def
.op
);
567 if (test_def
.precision
== LONG_TEST
) {
568 printf("%016llx", test_valB
.u64_val
);
570 printf("%016llx %016llx", test_valB
.u128
.valu
, test_valB
.u128
.vall
);
572 printf(" => %x (BF=%d)\n", condreg
, BF
);
584 { &test_dfp_test_significance_ops
,
585 "Test DFP test significance instructions"},
586 { &test_dfp_ddedpd_ops
,
587 "Test DFP DPD-to-BCD instructions"},
588 { &test_dfp_denbcd_ops
,
589 "Test DFP BCD-to-DPD instructions"},
598 test_driver_func_t func
;
601 while ((func
= all_tests
[i
].test_category
)) {
602 aTest
= all_tests
[i
];
603 printf( "%s\n", aTest
.name
);