mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-03 18:13:01 +00:00
POWER Processor decimal floating point instruction support: part 2
(bug #297497) (Carl Love, carll@us.ibm.com) (Valgrind side, mostly tests) git-svn-id: svn://svn.valgrind.org/valgrind/trunk@12500
This commit is contained in:
parent
5fd4b24eef
commit
9c1af9b09a
@ -3049,6 +3049,21 @@ IRAtom* expr2vbits_Binop ( MCEnv* mce,
|
||||
/* I32(rm) x I64/F64 -> I64/F64 */
|
||||
return mkLazy2(mce, Ity_I64, vatom1, vatom2);
|
||||
|
||||
case Iop_ShlD64:
|
||||
case Iop_ShrD64:
|
||||
/* I32(DFP rm) x D64 -> D64 */
|
||||
return mkLazy2(mce, Ity_I64, vatom1, vatom2);
|
||||
|
||||
case Iop_ShlD128:
|
||||
case Iop_ShrD128:
|
||||
/* I32(DFP rm) x D64 -> D128 */
|
||||
return mkLazy2(mce, Ity_I128, vatom1, vatom2);
|
||||
|
||||
case Iop_D64toI64S:
|
||||
case Iop_I64StoD64:
|
||||
/* I64(DFP rm) x I64 -> D64 */
|
||||
return mkLazy2(mce, Ity_I64, vatom1, vatom2);
|
||||
|
||||
case Iop_RoundF32toInt:
|
||||
case Iop_SqrtF32:
|
||||
/* I32(rm) x I32/F32 -> I32/F32 */
|
||||
@ -3069,6 +3084,8 @@ IRAtom* expr2vbits_Binop ( MCEnv* mce,
|
||||
|
||||
case Iop_F128toI64S: /* IRRoundingMode(I32) x F128 -> signed I64 */
|
||||
case Iop_F128toF64: /* IRRoundingMode(I32) x F128 -> F64 */
|
||||
case Iop_D128toD64: /* IRRoundingModeDFP(I64) x D128 -> D64 */
|
||||
case Iop_D128toI64S: /* IRRoundingModeDFP(I64) x D128 -> signed I64 */
|
||||
return mkLazy2(mce, Ity_I64, vatom1, vatom2);
|
||||
|
||||
case Iop_F64HLtoF128:
|
||||
@ -3082,6 +3099,10 @@ IRAtom* expr2vbits_Binop ( MCEnv* mce,
|
||||
/* First arg is I32 (rounding mode), second is F64 (data). */
|
||||
return mkLazy2(mce, Ity_I32, vatom1, vatom2);
|
||||
|
||||
case Iop_D64toD32:
|
||||
/* First arg is I64 (DFProunding mode), second is D64 (data). */
|
||||
return mkLazy2(mce, Ity_I64, vatom1, vatom2);
|
||||
|
||||
case Iop_F64toI16S:
|
||||
/* First arg is I32 (rounding mode), second is F64 (data). */
|
||||
return mkLazy2(mce, Ity_I16, vatom1, vatom2);
|
||||
@ -3376,6 +3397,7 @@ IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
|
||||
case Iop_I64StoF128: /* signed I64 -> F128 */
|
||||
case Iop_F32toF128: /* F32 -> F128 */
|
||||
case Iop_F64toF128: /* F64 -> F128 */
|
||||
case Iop_I64StoD128: /* signed I64 -> D128 */
|
||||
return mkPCastTo(mce, Ity_I128, vatom);
|
||||
|
||||
case Iop_F32toF64:
|
||||
@ -3390,8 +3412,12 @@ IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
|
||||
case Iop_RoundF64toF64_ZERO:
|
||||
case Iop_Clz64:
|
||||
case Iop_Ctz64:
|
||||
case Iop_D32toD64:
|
||||
return mkPCastTo(mce, Ity_I64, vatom);
|
||||
|
||||
case Iop_D64toD128:
|
||||
return mkPCastTo(mce, Ity_I128, vatom);
|
||||
|
||||
case Iop_Clz32:
|
||||
case Iop_Ctz32:
|
||||
case Iop_TruncF64asF32:
|
||||
|
||||
@ -30,7 +30,9 @@ EXTRA_DIST = \
|
||||
test_isa_2_06_part1.stderr.exp test_isa_2_06_part1.stdout.exp test_isa_2_06_part1.vgtest \
|
||||
test_isa_2_06_part2.stderr.exp test_isa_2_06_part2.stdout.exp test_isa_2_06_part2.vgtest \
|
||||
test_isa_2_06_part3.stderr.exp test_isa_2_06_part3.stdout.exp test_isa_2_06_part3.vgtest \
|
||||
test_dfp1.stderr.exp test_dfp1.stdout.exp test_dfp1.vgtest
|
||||
test_dfp1.stderr.exp test_dfp1.stdout.exp test_dfp1.vgtest \
|
||||
test_dfp2.stderr.exp test_dfp2.stdout.exp test_dfp2.vgtest \
|
||||
test_dfp2.stdout.exp_Without_dcffix
|
||||
|
||||
check_PROGRAMS = \
|
||||
allexec \
|
||||
@ -41,7 +43,7 @@ check_PROGRAMS = \
|
||||
test_isa_2_06_part1 \
|
||||
test_isa_2_06_part2 \
|
||||
test_isa_2_06_part3 \
|
||||
test_dfp1
|
||||
test_dfp1 test_dfp2
|
||||
|
||||
|
||||
AM_CFLAGS += @FLAG_M32@
|
||||
@ -89,3 +91,5 @@ test_isa_2_06_part3_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -lm -g -mregnames $(
|
||||
|
||||
test_dfp1_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -lm -g -mregnames $(DFP_FLAG) \
|
||||
@FLAG_M32@ $(BUILD_FLAGS_DFP)
|
||||
test_dfp2_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -lm -g -mregnames $(DFP_FLAG) \
|
||||
@FLAG_M32@ $(BUILD_FLAGS_DFP)
|
||||
|
||||
677
none/tests/ppc32/test_dfp2.c
Normal file
677
none/tests/ppc32/test_dfp2.c
Normal file
@ -0,0 +1,677 @@
|
||||
/* Copyright (C) 2012 IBM
|
||||
|
||||
Author: Maynard Johnson <maynardj@us.ibm.com>
|
||||
Carl Love <carll@us.ibm.com>
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
02111-1307, USA.
|
||||
|
||||
The GNU General Public License is contained in the file COPYING.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <elf.h>
|
||||
#include <link.h>
|
||||
|
||||
#define PPC_FEATURE_HAS_VSX 0x00000080 /* Vector Scalar Extension. */
|
||||
|
||||
#if defined(HAS_DFP)
|
||||
|
||||
register double f14 __asm__ ("fr14");
|
||||
register double f15 __asm__ ("fr15");
|
||||
register double f16 __asm__ ("fr16");
|
||||
register double f17 __asm__ ("fr17");
|
||||
register double f18 __asm__ ("fr18");
|
||||
register double f19 __asm__ ("fr19");
|
||||
|
||||
typedef unsigned char Bool;
|
||||
#define True 1
|
||||
#define False 0
|
||||
|
||||
#define SET_FPSCR_ZERO \
|
||||
do { double _d = 0.0; \
|
||||
__asm__ __volatile__ ("mtfsf 0xFF, %0" : : "f"(_d) ); \
|
||||
} while (0)
|
||||
|
||||
#define GET_FPSCR(_arg) \
|
||||
__asm__ __volatile__ ("mffs %0" : "=f"(_arg) )
|
||||
|
||||
#define SET_FPSCR_DRN \
|
||||
__asm__ __volatile__ ("mtfsf 1, %0, 0, 1" : : "f"(f14) )
|
||||
|
||||
#define SH_0 0
|
||||
#define SH_1 1
|
||||
#define SH_2 15
|
||||
#define SH_3 63
|
||||
|
||||
#define NUM_RND_MODES 8
|
||||
#define CONDREG_MASK 0x0f000000
|
||||
#define CONDREG_SHIFT 24
|
||||
|
||||
static char ** my_envp;
|
||||
static inline char** __auxv_find(void)
|
||||
{
|
||||
char **result = my_envp;
|
||||
/* Scan over the env vector looking for the ending NULL */
|
||||
for (; *result != NULL; ++result) {
|
||||
}
|
||||
/* Bump the pointer one more step, which should be the auxv. */
|
||||
return ++result;
|
||||
}
|
||||
|
||||
static unsigned long fetch_at_hwcap(void)
|
||||
{
|
||||
static unsigned long auxv_hwcap = 0;
|
||||
int i;
|
||||
ElfW(auxv_t) * auxv_buf = NULL;
|
||||
|
||||
if (auxv_hwcap)
|
||||
return auxv_hwcap;
|
||||
|
||||
auxv_buf = (ElfW(auxv_t)*) __auxv_find();
|
||||
for (i = 0; auxv_buf[i].a_type != AT_NULL; i++)
|
||||
if (auxv_buf[i].a_type == AT_HWCAP) {
|
||||
auxv_hwcap = auxv_buf[i].a_un.a_val;
|
||||
break;
|
||||
}
|
||||
|
||||
return auxv_hwcap;
|
||||
}
|
||||
|
||||
int get_vsx(void)
|
||||
{
|
||||
/* Check to see if the AUX vector has the bit set indicating the HW
|
||||
* supports the vsx instructions. This implies the processor is
|
||||
* at least a POWER 7.
|
||||
*/
|
||||
unsigned long hwcap;
|
||||
|
||||
hwcap = fetch_at_hwcap();
|
||||
if ((hwcap & PPC_FEATURE_HAS_VSX) == PPC_FEATURE_HAS_VSX)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The assembly-level instructions being tested */
|
||||
static void _test_dscri (int shift)
|
||||
{
|
||||
switch(shift) {
|
||||
case SH_0:
|
||||
__asm__ __volatile__ ("dscri %0, %1, %2" : "=f" (f18) : "f" (f14), "i" (SH_0));
|
||||
break;
|
||||
|
||||
case SH_1:
|
||||
__asm__ __volatile__ ("dscri %0, %1, %2" : "=f" (f18) : "f" (f14), "i" (SH_1));
|
||||
break;
|
||||
|
||||
case SH_2:
|
||||
__asm__ __volatile__ ("dscri %0, %1, %2" : "=f" (f18) : "f" (f14), "i" (SH_2));
|
||||
break;
|
||||
|
||||
case SH_3:
|
||||
__asm__ __volatile__ ("dscri %0, %1, %2" : "=f" (f18) : "f" (f14), "i" (SH_3));
|
||||
break;
|
||||
default:
|
||||
printf(" dscri, unsupported shift case %d\n", shift);
|
||||
}
|
||||
}
|
||||
|
||||
static void _test_dscli (int shift)
|
||||
{
|
||||
switch(shift) {
|
||||
case SH_0:
|
||||
__asm__ __volatile__ ("dscli %0, %1, %2" : "=f" (f18) : "f" (f14), "i" (SH_0));
|
||||
break;
|
||||
|
||||
case SH_1:
|
||||
__asm__ __volatile__ ("dscli %0, %1, %2" : "=f" (f18) : "f" (f14), "i" (SH_1));
|
||||
break;
|
||||
|
||||
case SH_2:
|
||||
__asm__ __volatile__ ("dscli %0, %1, %2" : "=f" (f18) : "f" (f14), "i" (SH_2));
|
||||
break;
|
||||
|
||||
case SH_3:
|
||||
__asm__ __volatile__ ("dscli %0, %1, %2" : "=f" (f18) : "f" (f14), "i" (SH_3));
|
||||
break;
|
||||
default:
|
||||
printf(" dscli, unsupported shift case %d\n", shift);
|
||||
}
|
||||
}
|
||||
|
||||
static void _test_dctdp (void)
|
||||
{
|
||||
__asm__ __volatile__ ("dctdp %0, %1" : "=f" (f18) : "f" (f14));
|
||||
}
|
||||
|
||||
static void _test_drsp (void)
|
||||
{
|
||||
__asm__ __volatile__ ("drsp %0, %1" : "=f" (f18) : "f" (f14));
|
||||
}
|
||||
|
||||
static void _test_dctfix (void)
|
||||
{
|
||||
__asm__ __volatile__ ("dctfix %0, %1" : "=f" (f18) : "f" (f14));
|
||||
}
|
||||
|
||||
/* Power 7 and newer processors support this instruction */
|
||||
static void _test_dcffix (void)
|
||||
{
|
||||
__asm__ __volatile__ ("dcffix %0, %1" : "=f" (f18) : "f" (f14));
|
||||
}
|
||||
|
||||
static void _test_dscriq (int shift)
|
||||
{
|
||||
switch(shift) {
|
||||
case SH_0:
|
||||
__asm__ __volatile__ ("dscriq %0, %1, %2" : "=f" (f18) : "f" (f14), "i" (SH_0));
|
||||
break;
|
||||
case SH_1:
|
||||
__asm__ __volatile__ ("dscriq %0, %1, %2" : "=f" (f18) : "f" (f14), "i" (SH_1));
|
||||
break;
|
||||
case SH_2:
|
||||
__asm__ __volatile__ ("dscriq %0, %1, %2" : "=f" (f18) : "f" (f14), "i" (SH_2));
|
||||
break;
|
||||
case SH_3:
|
||||
__asm__ __volatile__ ("dscriq %0, %1, %2" : "=f" (f18) : "f" (f14), "i" (SH_3));
|
||||
break;
|
||||
default:
|
||||
printf(" dscriq, unsupported shift case %d\n", shift);
|
||||
}
|
||||
}
|
||||
|
||||
static void _test_dscliq (int shift)
|
||||
{
|
||||
switch(shift) {
|
||||
case SH_0:
|
||||
__asm__ __volatile__ ("dscliq %0, %1, %2" : "=f" (f18) : "f" (f14), "i" (SH_0));
|
||||
break;
|
||||
case SH_1:
|
||||
__asm__ __volatile__ ("dscliq %0, %1, %2" : "=f" (f18) : "f" (f14), "i" (SH_1));
|
||||
break;
|
||||
case SH_2:
|
||||
__asm__ __volatile__ ("dscliq %0, %1, %2" : "=f" (f18) : "f" (f14), "i" (SH_2));
|
||||
break;
|
||||
case SH_3:
|
||||
__asm__ __volatile__ ("dscliq %0, %1, %2" : "=f" (f18) : "f" (f14), "i" (SH_3));
|
||||
break;
|
||||
default:
|
||||
printf(" dscliq, unsupported shift case %d\n", shift);
|
||||
}
|
||||
}
|
||||
|
||||
static void _test_dctqpq (void)
|
||||
{
|
||||
__asm__ __volatile__ ("dctqpq %0, %1" : "=f" (f18) : "f" (f14));
|
||||
}
|
||||
|
||||
static void _test_dctfixq (void)
|
||||
{
|
||||
__asm__ __volatile__ ("dctfixq %0, %1" : "=f" (f18) : "f" (f14));
|
||||
}
|
||||
|
||||
static void _test_drdpq (void)
|
||||
{
|
||||
__asm__ __volatile__ ("drdpq %0, %1" : "=f" (f18) : "f" (f14));
|
||||
}
|
||||
|
||||
static void _test_dcffixq (void)
|
||||
{
|
||||
__asm__ __volatile__ ("dcffixq %0, %1" : "=f" (f18) : "f" (f14));
|
||||
}
|
||||
|
||||
typedef void (*test_func_t)();
|
||||
typedef void (*test_func_main_t)(int);
|
||||
typedef void (*test_func_shift_t)(int);
|
||||
typedef struct test_table
|
||||
{
|
||||
test_func_main_t test_category;
|
||||
char * name;
|
||||
} test_table_t;
|
||||
|
||||
static unsigned long long dfp128_vals[] = {
|
||||
// Some finite numbers
|
||||
0x2207c00000000000ULL, 0x0000000000000e50ULL,
|
||||
0x2f07c00000000000ULL, 0x000000000014c000ULL, //large number
|
||||
0xa207c00000000000ULL, 0x00000000000000e0ULL,
|
||||
0x2206c00000000000ULL, 0x00000000000000cfULL,
|
||||
0xa205c00000000000ULL, 0x000000010a395bcfULL,
|
||||
0x6209400000fd0000ULL, 0x00253f1f534acdd4ULL, // a small number
|
||||
0x000400000089b000ULL, 0x0a6000d000000049ULL, // very small number
|
||||
// flavors of zero
|
||||
0x2208000000000000ULL, 0x0000000000000000ULL,
|
||||
0xa208000000000000ULL, 0x0000000000000000ULL, // negative
|
||||
0xa248000000000000ULL, 0x0000000000000000ULL,
|
||||
// flavors of NAN
|
||||
0x7c00000000000000ULL, 0x0000000000000000ULL, // quiet
|
||||
0xfc00000000000000ULL, 0xc00100035b007700ULL,
|
||||
0x7e00000000000000ULL, 0xfe000000d0e0a0d0ULL, // signaling
|
||||
// flavors of Infinity
|
||||
0x7800000000000000ULL, 0x0000000000000000ULL,
|
||||
0xf800000000000000ULL, 0x0000000000000000ULL, // negative
|
||||
0xf900000000000000ULL, 0x0000000000000000ULL
|
||||
};
|
||||
|
||||
static unsigned long long int64_vals[] = {
|
||||
// I64 values
|
||||
0x0ULL, // zero
|
||||
0x1ULL, // one
|
||||
0xffffffffffffffffULL, // minus one
|
||||
0x2386f26fc0ffffULL, // 9999999999999999
|
||||
0xffdc790d903f0001ULL, // -9999999999999999
|
||||
0x462d53c8abac0ULL, // 1234567890124567
|
||||
0xfffb9d2ac3754540ULL, // -1234567890124567
|
||||
};
|
||||
|
||||
static unsigned long long dfp64_vals[] = {
|
||||
// various finite numbers
|
||||
0x2234000000000e50ULL,
|
||||
0x223400000014c000ULL,
|
||||
0xa2340000000000e0ULL,// negative
|
||||
0x22240000000000cfULL,
|
||||
0xa21400010a395bcfULL,// negative
|
||||
0x6e4d3f1f534acdd4ULL,// large number
|
||||
0x000400000089b000ULL,// very small number
|
||||
// flavors of zero
|
||||
0x2238000000000000ULL,
|
||||
0xa238000000000000ULL,
|
||||
0x4248000000000000ULL,
|
||||
// flavors of NAN
|
||||
0x7e34000000000111ULL,
|
||||
0xfe000000d0e0a0d0ULL,//signaling
|
||||
0xfc00000000000000ULL,//quiet
|
||||
// flavors of Infinity
|
||||
0x7800000000000000ULL,
|
||||
0xf800000000000000ULL,//negative
|
||||
0x7a34000000000000ULL,
|
||||
};
|
||||
|
||||
|
||||
typedef struct dfp_test_args {
|
||||
int fra_idx;
|
||||
int frb_idx;
|
||||
} dfp_test_args_t;
|
||||
|
||||
|
||||
/* Index pairs from dfp64_vals or dfp128_vals array to be used with
|
||||
* dfp_two_arg_tests */
|
||||
static dfp_test_args_t int64_args_x1[] = {
|
||||
/* {int64 input val, unused } */
|
||||
{0, 0},
|
||||
{1, 0},
|
||||
{2, 0},
|
||||
{3, 0},
|
||||
{4, 0},
|
||||
{5, 0},
|
||||
{6, 0},
|
||||
};
|
||||
|
||||
static dfp_test_args_t dfp_2args_x1[] = {
|
||||
/* {dfp_arg, shift_arg} */
|
||||
{0, SH_0},
|
||||
{0, SH_1},
|
||||
{0, SH_2},
|
||||
{0, SH_3},
|
||||
{5, SH_0},
|
||||
{5, SH_1},
|
||||
{5, SH_2},
|
||||
{5, SH_3},
|
||||
{6, SH_0},
|
||||
{6, SH_1},
|
||||
{6, SH_2},
|
||||
{6, SH_3},
|
||||
{7, SH_0},
|
||||
{7, SH_1},
|
||||
{7, SH_2},
|
||||
{7, SH_3},
|
||||
{10, SH_0},
|
||||
{10, SH_1},
|
||||
{10, SH_2},
|
||||
{10, SH_3},
|
||||
{13, SH_0},
|
||||
{13, SH_1},
|
||||
{13, SH_2},
|
||||
{13, SH_3},
|
||||
};
|
||||
|
||||
/* Index pairs from dfp64_vals array to be used with dfp_one_arg_tests */
|
||||
static dfp_test_args_t dfp_1args_x1[] = {
|
||||
/* {dfp_arg, unused} */
|
||||
{0, 0},
|
||||
{1, 0},
|
||||
{2, 0},
|
||||
{3, 0},
|
||||
{4, 0},
|
||||
{5, 0},
|
||||
{6, 0},
|
||||
{7, 0},
|
||||
{8, 0},
|
||||
{9, 0},
|
||||
{10, 0},
|
||||
{11, 0},
|
||||
{12, 0},
|
||||
{13, 0},
|
||||
{14, 0},
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
LONG_TEST,
|
||||
QUAD_TEST
|
||||
} precision_type_t;
|
||||
|
||||
typedef struct dfp_test
|
||||
{
|
||||
test_func_t test_func;
|
||||
const char * name;
|
||||
dfp_test_args_t * targs;
|
||||
int num_tests;
|
||||
precision_type_t precision;
|
||||
const char * op;
|
||||
Bool cr_supported;
|
||||
} dfp_test_t;
|
||||
|
||||
/* The dcffix and dcffixq tests are a little different in that they both take
|
||||
* an I64 input.
|
||||
*/
|
||||
static dfp_test_t
|
||||
dfp_dcffix_dcffixq_tests[] = {
|
||||
{ &_test_dcffixq,"dcffixq", int64_args_x1, 7, QUAD_TEST, "I64S->D128", True},
|
||||
/* Power 7 instruction */
|
||||
{ &_test_dcffix, "dcffix", int64_args_x1, 7, LONG_TEST, "I64S->D64", True},
|
||||
{ NULL, NULL, NULL, 0, 0, NULL}
|
||||
};
|
||||
|
||||
static dfp_test_t
|
||||
dfp_one_arg_tests[] = {
|
||||
{ &_test_dctdp, "dctdp", dfp_1args_x1, 15, LONG_TEST, "D32->D64", True},
|
||||
{ &_test_drsp, "drsp", dfp_1args_x1, 15, LONG_TEST, "D64->D32", True},
|
||||
{ &_test_dctfix, "dctfix", dfp_1args_x1, 15, LONG_TEST, "D64->I64S", True},
|
||||
{ &_test_dctqpq, "dctqpq", dfp_1args_x1, 15, QUAD_TEST, "D64->D128", True},
|
||||
{ &_test_dctfixq,"dctfixq", dfp_1args_x1, 15, QUAD_TEST, "D128->I64S", True},
|
||||
{ &_test_drdpq, "drdpq", dfp_1args_x1, 15, QUAD_TEST, "D128->D64", True},
|
||||
{ NULL, NULL, NULL, 0, 0, NULL}
|
||||
};
|
||||
|
||||
|
||||
static dfp_test_t
|
||||
dfp_two_arg_tests[] = {
|
||||
{ &_test_dscri, "dscri", dfp_2args_x1, 20, LONG_TEST, ">>", True},
|
||||
{ &_test_dscli, "dscli", dfp_2args_x1, 20, LONG_TEST, "<<", True},
|
||||
{ &_test_dscriq, "dscriq", dfp_2args_x1, 20, QUAD_TEST, ">>", True},
|
||||
{ &_test_dscliq, "dscliq", dfp_2args_x1, 20, QUAD_TEST, "<<", True},
|
||||
{ NULL, NULL, NULL, 0, 0, NULL}
|
||||
};
|
||||
|
||||
void set_rounding_mode(unsigned long long rnd_mode)
|
||||
{
|
||||
double fpscr;
|
||||
unsigned long long * hex_fpscr = (unsigned long long *)&fpscr;
|
||||
|
||||
*hex_fpscr = 0ULL;
|
||||
__asm__ __volatile__ ("mffs %0" : "=f"(f14));
|
||||
fpscr = f14;
|
||||
*hex_fpscr &= 0xFFFFFFF0FFFFFFFFULL;
|
||||
*hex_fpscr |= (rnd_mode << 32);
|
||||
f14 = fpscr;
|
||||
SET_FPSCR_DRN;
|
||||
}
|
||||
|
||||
static void test_dfp_one_arg_ops(int unused)
|
||||
{
|
||||
test_func_t func;
|
||||
unsigned long long u0, u0x;
|
||||
double res, d0, *d0p;
|
||||
double d0x, *d0xp;
|
||||
unsigned long round_mode;
|
||||
int k = 0;
|
||||
|
||||
u0x = 0;
|
||||
d0p = &d0;
|
||||
d0xp = &d0x;
|
||||
|
||||
while ((func = dfp_one_arg_tests[k].test_func)) {
|
||||
int i;
|
||||
|
||||
for (round_mode = 0; round_mode < NUM_RND_MODES; round_mode++) {
|
||||
/* Do each test with each of the possible rounding modes */
|
||||
dfp_test_t test_group = dfp_one_arg_tests[k];
|
||||
|
||||
printf("\ntest with rounding mode %lu \n", round_mode);
|
||||
/* The set_rounding_mode() uses the global value f14. Call the
|
||||
* function before setting up the test for the specific instruction
|
||||
* to avoid avoid conflicts using f14.
|
||||
*/
|
||||
set_rounding_mode(round_mode);
|
||||
|
||||
for (i = 0; i < test_group.num_tests; i++) {
|
||||
|
||||
if (test_group.precision == LONG_TEST) {
|
||||
u0 = dfp64_vals[test_group.targs[i].fra_idx];
|
||||
} else {
|
||||
u0 = dfp128_vals[test_group.targs[i].fra_idx * 2];
|
||||
u0x = dfp128_vals[(test_group.targs[i].fra_idx * 2) + 1];
|
||||
}
|
||||
|
||||
*(unsigned long long *)d0p = u0;
|
||||
f14 = d0;
|
||||
if (test_group.precision == QUAD_TEST) {
|
||||
*(unsigned long long *)d0xp = u0x;
|
||||
f15 = d0x;
|
||||
}
|
||||
|
||||
(*func)();
|
||||
res = f18;
|
||||
|
||||
printf("%s %016llx", test_group.name, u0);
|
||||
|
||||
if (test_group.precision == LONG_TEST) {
|
||||
printf(" %s => %016llx",
|
||||
test_group.op, *((unsigned long long *)(&res)));
|
||||
} else {
|
||||
double resx = f19;
|
||||
printf(" %016llx %s ==> %016llx %016llx",
|
||||
u0x, test_group.op,
|
||||
*((unsigned long long *)(&res)),
|
||||
*((unsigned long long *)(&resx)));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
k++;
|
||||
printf( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
static void test_dfp_two_arg_ops(int unused)
|
||||
/* Shift instructions: first argument is the DFP source, second argument
|
||||
* is 6 bit shift amount.
|
||||
*/
|
||||
{
|
||||
test_func_shift_t func;
|
||||
unsigned long long u0, u0x;
|
||||
unsigned int shift_by;
|
||||
double res, d0, *d0p;
|
||||
double d0x, *d0xp;
|
||||
unsigned long round_mode;
|
||||
int k = 0;
|
||||
|
||||
u0x = 0;
|
||||
d0p = &d0;
|
||||
d0xp = &d0x;
|
||||
|
||||
while ((func = dfp_two_arg_tests[k].test_func)) {
|
||||
int i;
|
||||
|
||||
for (round_mode = 0; round_mode < NUM_RND_MODES; round_mode++) {
|
||||
/* Do each test with each of the possible rounding modes */
|
||||
dfp_test_t test_group = dfp_two_arg_tests[k];
|
||||
|
||||
printf("\ntest with rounding mode %lu \n", round_mode);
|
||||
|
||||
/* The set_rounding_mode() uses the global value f14. Call the
|
||||
* function before setting up the test for the specific instruction
|
||||
* to avoid avoid conflicts using f14.
|
||||
*/
|
||||
set_rounding_mode(round_mode);
|
||||
|
||||
for (i = 0; i < test_group.num_tests; i++) {
|
||||
|
||||
shift_by = test_group.targs[i].frb_idx;
|
||||
|
||||
if (test_group.precision == LONG_TEST) {
|
||||
u0 = dfp64_vals[test_group.targs[i].fra_idx];
|
||||
} else {
|
||||
u0 = dfp128_vals[test_group.targs[i].fra_idx * 2];
|
||||
u0x = dfp128_vals[(test_group.targs[i].fra_idx * 2) + 1];
|
||||
}
|
||||
|
||||
*(unsigned long long *)d0p = u0;
|
||||
f14 = d0;
|
||||
if (test_group.precision == QUAD_TEST) {
|
||||
*(unsigned long long *)d0xp = u0x;
|
||||
f15 = d0x;
|
||||
}
|
||||
|
||||
(*func)(shift_by);
|
||||
res = f18;
|
||||
|
||||
printf("%s %016llx", test_group.name, u0);
|
||||
|
||||
if (test_group.precision) {
|
||||
printf(" %s %-3d => %016llx",
|
||||
test_group.op, shift_by, *((unsigned long long *)(&res)));
|
||||
} else {
|
||||
double resx = f19;
|
||||
printf(" %016llx %s %-3d ==> %016llx %016llx",
|
||||
u0x, test_group.op, shift_by,
|
||||
*((unsigned long long *)(&res)),
|
||||
*((unsigned long long *)(&resx)));
|
||||
}
|
||||
printf("\n" );
|
||||
}
|
||||
}
|
||||
|
||||
k++;
|
||||
printf( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
static void test_dcffix_dcffixq(int has_vsx)
|
||||
{
|
||||
test_func_t func;
|
||||
unsigned long long u0, u0x;
|
||||
double res, d0, *d0p;
|
||||
double d0x, *d0xp;
|
||||
int k = 0, round_mode;
|
||||
|
||||
u0x = 0;
|
||||
d0p = &d0;
|
||||
d0xp = &d0x;
|
||||
|
||||
while ((func = dfp_dcffix_dcffixq_tests[k].test_func)) {
|
||||
int i;
|
||||
|
||||
if ((!has_vsx) && (!strcmp("dcffix", dfp_dcffix_dcffixq_tests[k].name))) {
|
||||
k++;
|
||||
/* The test instruction is dcffix it is supported on POWER 7
|
||||
* and newer processors. Skip if not POWER 7 or newer.
|
||||
*/
|
||||
continue;
|
||||
}
|
||||
|
||||
for (round_mode = 0; round_mode < NUM_RND_MODES; round_mode++) {
|
||||
/* Do each test with each of the possible rounding modes */
|
||||
dfp_test_t test_group = dfp_dcffix_dcffixq_tests[k];
|
||||
|
||||
printf("\ntest with rounding mode %u \n", round_mode);
|
||||
|
||||
/* The set_rounding_mode() uses the global value f14. Call the
|
||||
* function before setting up the test for the specific instruction
|
||||
* to avoid avoid conflicts using f14.
|
||||
*/
|
||||
set_rounding_mode(round_mode);
|
||||
|
||||
for (i = 0; i < test_group.num_tests; i++) {
|
||||
|
||||
/* The instructions take I64 inputs */
|
||||
u0 = int64_vals[test_group.targs[i].fra_idx];
|
||||
|
||||
*(unsigned long long *)d0p = u0;
|
||||
f14 = d0;
|
||||
|
||||
(*func)();
|
||||
res = f18;
|
||||
|
||||
printf("%s %016llx", test_group.name, u0);
|
||||
|
||||
if (test_group.precision) {
|
||||
printf(" %s => %016llx",
|
||||
test_group.op, *((unsigned long long *)(&res)));
|
||||
} else {
|
||||
double resx = f19;
|
||||
printf(" %s ==> %016llx %016llx",
|
||||
test_group.op,
|
||||
*((unsigned long long *)(&res)),
|
||||
*((unsigned long long *)(&resx)));
|
||||
}
|
||||
printf("\n" );
|
||||
}
|
||||
}
|
||||
|
||||
k++;
|
||||
printf( "\n" );
|
||||
}
|
||||
}
|
||||
|
||||
static test_table_t
|
||||
all_tests[] =
|
||||
{
|
||||
{ &test_dfp_one_arg_ops,
|
||||
"Test DFP fomat conversion instructions" },
|
||||
{ &test_dfp_two_arg_ops,
|
||||
"Test DFP shift instructions" },
|
||||
{ test_dcffix_dcffixq,
|
||||
"Test DCFFIX and DCFFIXQ instructions" },
|
||||
{ NULL, NULL }
|
||||
};
|
||||
#endif // HAS_DFP
|
||||
|
||||
int main(int argc, char ** argv, char ** envp) {
|
||||
#if defined(HAS_DFP)
|
||||
test_table_t aTest;
|
||||
test_func_t func;
|
||||
int i = 0, has_vsx;
|
||||
|
||||
/* If the processor has the VSX functionality then it is POWER 7
|
||||
* or newer.
|
||||
*/
|
||||
my_envp = envp;
|
||||
has_vsx = get_vsx();
|
||||
|
||||
while ((func = all_tests[i].test_category)) {
|
||||
aTest = all_tests[i];
|
||||
printf( "%s\n", aTest.name );
|
||||
(*func)(has_vsx);
|
||||
i++;
|
||||
}
|
||||
|
||||
#endif // HAS_DFP
|
||||
return 0;
|
||||
}
|
||||
2
none/tests/ppc32/test_dfp2.stderr.exp
Normal file
2
none/tests/ppc32/test_dfp2.stderr.exp
Normal file
@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
1679
none/tests/ppc32/test_dfp2.stdout.exp
Normal file
1679
none/tests/ppc32/test_dfp2.stdout.exp
Normal file
File diff suppressed because it is too large
Load Diff
1606
none/tests/ppc32/test_dfp2.stdout.exp_Without_dcffix
Normal file
1606
none/tests/ppc32/test_dfp2.stdout.exp_Without_dcffix
Normal file
File diff suppressed because it is too large
Load Diff
2
none/tests/ppc32/test_dfp2.vgtest
Normal file
2
none/tests/ppc32/test_dfp2.vgtest
Normal file
@ -0,0 +1,2 @@
|
||||
prereq: ../../../tests/check_dfp_cap
|
||||
prog: test_dfp2
|
||||
@ -18,12 +18,14 @@ EXTRA_DIST = \
|
||||
test_isa_2_06_part1.stderr.exp test_isa_2_06_part1.stdout.exp test_isa_2_06_part1.vgtest \
|
||||
test_isa_2_06_part2.stderr.exp test_isa_2_06_part2.stdout.exp test_isa_2_06_part2.vgtest \
|
||||
test_isa_2_06_part3.stderr.exp test_isa_2_06_part3.stdout.exp test_isa_2_06_part3.vgtest \
|
||||
test_dfp1.stderr.exp test_dfp1.stdout.exp test_dfp1.vgtest
|
||||
test_dfp1.stderr.exp test_dfp1.stdout.exp test_dfp1.vgtest \
|
||||
test_dfp2.stderr.exp test_dfp2.stdout.exp test_dfp2.vgtest \
|
||||
test_dfp2.stdout.exp_Without_dcffix
|
||||
|
||||
check_PROGRAMS = \
|
||||
allexec \
|
||||
jm-insns lsw round std_reg_imm twi_tdi tw_td power6_bcmp power6_mf_gpr test_isa_2_06_part1 \
|
||||
test_isa_2_06_part2 test_isa_2_06_part3 test_dfp1
|
||||
test_isa_2_06_part2 test_isa_2_06_part3 test_dfp1 test_dfp2
|
||||
|
||||
AM_CFLAGS += @FLAG_M64@
|
||||
AM_CXXFLAGS += @FLAG_M64@
|
||||
@ -67,4 +69,7 @@ jm_insns_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -g -mregnames -maltivec \
|
||||
|
||||
test_dfp1_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -lm -g -mregnames $(DFP_FLAG) \
|
||||
@FLAG_M64@ $(BUILD_FLAGS_DFP)
|
||||
test_dfp2_CFLAGS = $(AM_CFLAGS) -Winline -Wall -O -lm -g -mregnames $(DFP_FLAG) \
|
||||
@FLAG_M64@ $(BUILD_FLAGS_DFP)
|
||||
|
||||
|
||||
|
||||
1
none/tests/ppc64/test_dfp2.c
Symbolic link
1
none/tests/ppc64/test_dfp2.c
Symbolic link
@ -0,0 +1 @@
|
||||
../../../none/tests/ppc32/test_dfp2.c
|
||||
2
none/tests/ppc64/test_dfp2.stderr.exp
Normal file
2
none/tests/ppc64/test_dfp2.stderr.exp
Normal file
@ -0,0 +1,2 @@
|
||||
|
||||
|
||||
2
none/tests/ppc64/test_dfp2.vgtest
Normal file
2
none/tests/ppc64/test_dfp2.vgtest
Normal file
@ -0,0 +1,2 @@
|
||||
prereq: ../../../tests/check_dfp_cap
|
||||
prog: test_dfp2
|
||||
Loading…
x
Reference in New Issue
Block a user