From: Cerion Armour-Brown Date: Fri, 2 Dec 2005 15:55:27 +0000 (+0000) Subject: Added tests for ppc32 floating point load/stores X-Git-Tag: svn/VALGRIND_3_2_0~555 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=3d699706f061ae1fc66e0984d62a4608a2afb499;p=thirdparty%2Fvalgrind.git Added tests for ppc32 floating point load/stores - not yet set to run in automated test. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@5267 --- diff --git a/none/tests/ppc32/jm-insns.c b/none/tests/ppc32/jm-insns.c index d070716c95..12ea93c9ee 100644 --- a/none/tests/ppc32/jm-insns.c +++ b/none/tests/ppc32/jm-insns.c @@ -221,6 +221,28 @@ enum test_flags { #define FDPRINTF(fmt, args...) do { } while (0) #endif +/* Produce the 64-bit pattern corresponding to the supplied double. */ +static uint64_t double_to_bits ( double d ) +{ + union { uint64_t i; double d; } u; + assert(8 == sizeof(uint64_t)); + assert(8 == sizeof(double)); + assert(8 == sizeof(u)); + u.d = d; + return u.i; +} + +#if 0 +static float bits_to_float ( uint32_t i ) +{ + union { uint32_t i; float f; } u; + assert(4 == sizeof(uint32_t)); + assert(4 == sizeof(float)); + assert(4 == sizeof(u)); + u.i = i; + return u.f; +} +#endif #define unused __attribute__ (( unused )) @@ -1745,6 +1767,154 @@ static test_t tests_flr_ops_spe[] = { }; #endif /* !defined (NO_FLOAT) */ + +#if !defined (NO_FLOAT) +extern void test_lfs (void); +asm(".text\n" + "test_lfs:\n" + "\tlfs 17,0(14)\n" + "\tblr\n" + ".previous\n" +); + +extern void test_lfsu (void); +asm(".text\n" + "test_lfsu:\n" + "\tlfsu 17,0(14)\n" + "\tblr\n" + ".previous\n" +); + +extern void test_lfd (void); +asm(".text\n" + "test_lfd:\n" + "\tlfd 17,0(14)\n" + "\tblr\n" + ".previous\n" +); + +extern void test_lfdu (void); +asm(".text\n" + "test_lfdu:\n" + "\tlfdu 17,0(14)\n" + "\tblr\n" + ".previous\n" +); + +static test_t tests_fld_ops_two_i16[] = { + { &test_lfs , " lfs", }, + { &test_lfsu , " lfsu", }, + { &test_lfd , " lfd", }, + { &test_lfdu , " lfdu", }, + { NULL, NULL, }, +}; +#endif /* !defined (NO_FLOAT) */ + +#if !defined (NO_FLOAT) +static void test_lfsx (void) +{ + __asm__ __volatile__ ("lfsx 17,14,15"); +} + +static void test_lfsux (void) +{ + __asm__ __volatile__ ("lfsux 17,14,15"); +} + +static void test_lfdx (void) +{ + __asm__ __volatile__ ("lfdx 17,14,15"); +} + +static void test_lfdux (void) +{ + __asm__ __volatile__ ("lfdux 17,14,15"); +} + +static test_t tests_fld_ops_two[] = { + { &test_lfsx , " lfsx", }, + { &test_lfsux , " lfsux", }, + { &test_lfdx , " lfdx", }, + { &test_lfdux , " lfdux", }, + { NULL, NULL, }, +}; +#endif /* !defined (NO_FLOAT) */ + +#if !defined (NO_FLOAT) +extern void test_stfs (void); +asm(".text\n" + "test_stfs:\n" + "\tstfs 14,0(15)\n" + "\tblr\n" + ".previous\n" +); + +extern void test_stfsu (void); +asm(".text\n" + "test_stfsu:\n" + "\tstfsu 14,0(15)\n" + "\tblr\n" + ".previous\n" +); + +extern void test_stfd (void); +asm(".text\n" + "test_stfd:\n" + "\tstfd 14,0(15)\n" + "\tblr\n" + ".previous\n" +); + +extern void test_stfdu (void); +asm(".text\n" + "test_stfdu:\n" + "\tstfdu 14,0(15)\n" + "\tblr\n" + ".previous\n" +); + +static test_t tests_fst_ops_three_i16[] = { +// TODO: Fix VEX to stop rounding these twice... +// { &test_stfs , " stfs", }, +// { &test_stfsu , " stfsu", }, + { &test_stfd , " stfd", }, + { &test_stfdu , " stfdu", }, + { NULL, NULL, }, +}; +#endif /* !defined (NO_FLOAT) */ + +#if !defined (NO_FLOAT) +static void test_stfsx (void) +{ + __asm__ __volatile__ ("stfsx 14,15,16"); +} + +static void test_stfsux (void) +{ + __asm__ __volatile__ ("stfsux 14,15,16"); +} + +static void test_stfdx (void) +{ + __asm__ __volatile__ ("stfdx 14,15,16"); +} + +static void test_stfdux (void) +{ + __asm__ __volatile__ ("stfdux 14,15,16"); +} + +static test_t tests_fst_ops_three[] = { +// TODO: Fix VEX to stop rounding these twice... +// { &test_stfsx , " stfsx", }, +// { &test_stfsux , " stfsux", }, + { &test_stfdx , " stfdx", }, + { &test_stfdux , " stfdux", }, + { NULL, NULL, }, +}; +#endif /* !defined (NO_FLOAT) */ + + #if defined (HAS_ALTIVEC) static void test_vmhaddshs (void) { @@ -3509,7 +3679,7 @@ static test_table_t all_tests[] = { #endif /* !defined (NO_FLOAT) */ #if !defined (NO_FLOAT) { - tests_far_ops_three , + tests_far_ops_three , "PPC floating point arith insns\n with three args with flags update", 0x01020103, }, @@ -3563,6 +3733,34 @@ static test_table_t all_tests[] = { 0x01020207, }, #endif /* !defined (NO_FLOAT) */ +#if !defined (NO_FLOAT) + { + tests_fld_ops_two_i16 , + "PPC float load insns\n with one register + one 16 bits immediate args with flags update", + 0x00020508, + }, +#endif /* !defined (NO_FLOAT) */ +#if !defined (NO_FLOAT) + { + tests_fld_ops_two , + "PPC float load insns with two register args", + 0x00020509, + }, +#endif /* !defined (NO_FLOAT) */ +#if !defined (NO_FLOAT) + { + tests_fst_ops_three_i16, + "PPC float store insns\n with one register + one 16 bits immediate args with flags update", + 0x0002050a, + }, +#endif /* !defined (NO_FLOAT) */ +#if !defined (NO_FLOAT) + { + tests_fst_ops_three , + "PPC float store insns with three register args", + 0x0002050b, + }, +#endif /* !defined (NO_FLOAT) */ #if defined (HAS_ALTIVEC) { tests_aa_ops_three , @@ -3725,19 +3923,34 @@ static inline void register_farg (void *farg, static void build_fargs_table (void) { - /* Sign goes from zero to one - * Exponent goes from 0 to ((1 << 12) - 1) - * Mantissa goes from 1 to ((1 << 52) - 1) + /* Double precision: + * Sign goes from zero to one (1 bit) + * Exponent goes from 0 to ((1 << 12) - 1) (11 bits) + * Mantissa goes from 1 to ((1 << 52) - 1) (52 bits) * + special values: - * +0.0 : 0 0x000 0x0000000000000 - * -0.0 : 1 0x000 0x0000000000000 - * +infinity : 0 0x7FF 0x0000000000000 - * -infinity : 1 0x7FF 0x0000000000000 - * +SNaN : 0 0x7FF 0x7FFFFFFFFFFFF - * -SNaN : 1 0x7FF 0x7FFFFFFFFFFFF - * +QNaN : 0 0x7FF 0x8000000000000 - * -QNaN : 1 0x7FF 0x8000000000000 + * +0.0 : 0 0x000 0x0000000000000 => 0x0000000000000000 + * -0.0 : 1 0x000 0x0000000000000 => 0x8000000000000000 + * +infinity : 0 0x7FF 0x0000000000000 => 0x7FF0000000000000 + * -infinity : 1 0x7FF 0x0000000000000 => 0xFFF0000000000000 + * +QNaN : 0 0x7FF 0x7FFFFFFFFFFFF => 0x7FF7FFFFFFFFFFFF + * -QNaN : 1 0x7FF 0x7FFFFFFFFFFFF => 0xFFF7FFFFFFFFFFFF + * +SNaN : 0 0x7FF 0x8000000000000 => 0x7FF8000000000000 + * -SNaN : 1 0x7FF 0x8000000000000 => 0xFFF8000000000000 * (8 values) + + * Ref only: + * Single precision + * Sign: 1 bit + * Exponent: 8 bits + * Mantissa: 23 bits + * +0.0 : 0 0x00 0x000000 => 0x00000000 + * -0.0 : 1 0x00 0x000000 => 0x80000000 + * +infinity : 0 0xFF 0x000000 => 0x7F800000 + * -infinity : 1 0xFF 0x000000 => 0xFF800000 + * +QNaN : 0 0xFF 0x3FFFFF => 0x7FBFFFFF + * -QNaN : 1 0xFF 0x3FFFFF => 0xFFBFFFFF + * +SNaN : 0 0xFF 0x400000 => 0x7FC00000 + * -SNaN : 1 0xFF 0x400000 => 0xFFC00000 */ uint64_t mant; uint16_t exp, e0, e1; @@ -3805,27 +4018,28 @@ static void build_fargs_table (void) exp = 0x7FF; mant = 0x0000000000000ULL; register_farg(&fargs[i++], s, exp, mant); - /* +SNaN : 0 0x7FF 0x7FFFFFFFFFFFF */ + /* +QNaN : 0 0x7FF 0x7FFFFFFFFFFFF */ s = 0; exp = 0x7FF; mant = 0x7FFFFFFFFFFFFULL; register_farg(&fargs[i++], s, exp, mant); - /* -SNaN : 1 0x7FF 0x7FFFFFFFFFFFF */ + /* -QNaN : 1 0x7FF 0x7FFFFFFFFFFFF */ s = 1; exp = 0x7FF; mant = 0x7FFFFFFFFFFFFULL; register_farg(&fargs[i++], s, exp, mant); - /* +QNaN : 0 0x7FF 0x8000000000000 */ + /* +SNaN : 0 0x7FF 0x8000000000000 */ s = 0; exp = 0x7FF; mant = 0x8000000000000ULL; register_farg(&fargs[i++], s, exp, mant); - /* -QNaN : 1 0x7FF 0x8000000000000 */ + /* -SNaN : 1 0x7FF 0x8000000000000 */ s = 1; exp = 0x7FF; mant = 0x8000000000000ULL; register_farg(&fargs[i++], s, exp, mant); AB_DPRINTF("Registered %d fargs values\n", i); + nb_fargs = i; } @@ -3920,11 +4134,9 @@ static inline void register_vfarg (vector float* vfarg, vector uint32_t* vfargI = (vector uint32_t*)vfarg; tmp = ((uint64_t)s << 31) | ((uint64_t)exp << 23) | mant; - //float f = *(float*)&tmp; - //*vfarg = (vector float){ f,f,f,f }; *vfargI = (vector uint32_t){ tmp,tmp,tmp,tmp }; AB_DPRINTF("%d %02x %06x => %08x %0e\n", - s, exp, mant, *((uint32_t*)&tmp), f); + s, exp, mant, *((uint32_t*)&tmp), *(float*)&tmp); } static void build_vfargs_table (void) @@ -5128,12 +5340,12 @@ static void test_int_ld_one_reg_imm16 (const char* name, // +ve d for (i=0; i r14 + offs + r14 = base; + + /* Save flags */ + __asm__ __volatile__ ("mfcr 18"); + tmpcr = r18; + __asm__ __volatile__ ("mfxer 18"); + tmpxer = r18; + + /* Set up flags for test */ + r18 = 0; + __asm__ __volatile__ ("mtcr 18"); + __asm__ __volatile__ ("mtxer 18"); + (*func)(); + __asm__ __volatile__ ("mfcr 18"); + flags = r18; + __asm__ __volatile__ ("mfxer 18"); + xer = r18; + res = f17; + + /* Restore flags */ + r18 = tmpcr; + __asm__ __volatile__ ("mtcr 18"); + r18 = tmpxer; + __asm__ __volatile__ ("mtxer 18"); + + printf("%s %016llx, %4d => %016llx, %08x (%08x %08x)\n", + name, double_to_bits(src), offs, + double_to_bits(res), r14, flags, xer); + } + if (verbose) printf("\n"); +} + +static void test_float_ld_two_regs (const char* name, + test_func_t func, + unused uint32_t test_flags) +{ + volatile uint32_t base, flags, xer, tmpcr, tmpxer; + volatile double src, res; + int i; + + /* offset within [1-nb_fargs:nb_fargs] */ + for (i=1-nb_fargs; i %016llx, %08x (%08x %08x)\n", + name, double_to_bits(src), r15, + double_to_bits(res), r14, flags, xer); + } +} + +static void test_float_st_two_regs_imm16 (const char* name, + test_func_t func, + unused uint32_t test_flags) +{ + uint32_t base, func_buf[2], *p; + volatile uint32_t flags, xer, tmpcr, tmpxer; + double src, *p_dst; + int i, offs; + double *fargs_priv; + + // private fargs table to store to + fargs_priv = malloc(nb_fargs * sizeof(double)); + + /* offset within [1-nb_fargs:nb_fargs] */ + for (i=1-nb_fargs; i f14 + // store to fargs_priv[idx] => r15 + offs + f14 = src; + r15 = base; + + /* Save flags */ + __asm__ __volatile__ ("mfcr 18"); + tmpcr = r18; + __asm__ __volatile__ ("mfxer 18"); + tmpxer = r18; + + /* Set up flags for test */ + r18 = 0; + __asm__ __volatile__ ("mtcr 18"); + __asm__ __volatile__ ("mtxer 18"); + (*func)(); + __asm__ __volatile__ ("mfcr 18"); + flags = r18; + __asm__ __volatile__ ("mfxer 18"); + xer = r18; + + /* Restore flags */ + r18 = tmpcr; + __asm__ __volatile__ ("mtcr 18"); + r18 = tmpxer; + __asm__ __volatile__ ("mtxer 18"); + + printf("%s %016llx, %4d => %016llx, %08x (%08x %08x)\n", + name, double_to_bits(src), offs, + double_to_bits(*p_dst), r15, flags, xer); + } + free(fargs_priv); +} + +static void test_float_st_three_regs (const char* name, + test_func_t func, + unused uint32_t test_flags) +{ + volatile uint32_t base, flags, xer, tmpcr, tmpxer; + double src, *p_dst; + int i, offs; + double *fargs_priv; + + // private fargs table to store to + fargs_priv = malloc(nb_fargs * sizeof(double)); + + // /* offset within [1-nb_fargs:nb_fargs] */ + // for (i=1-nb_fargs; i %016llx (%014e), %08x (%08x %08x)\n", + name, double_to_bits(src), src, offs, + double_to_bits(*p_dst), *p_dst, r15, flags, xer); +#else + // print single precision result + printf("%s %016llx (%014e), %4d => %08x (%f), %08x (%08x %08x)\n", + name, double_to_bits(src), src, offs, + (uint32_t)(double_to_bits(*p_dst) >> 32), + bits_to_float( (uint32_t)(double_to_bits(*p_dst) >> 32) ), + r15, flags, xer); +#endif + } + free(fargs_priv); +} + + /* Used in do_tests, indexed by flags->nb_args Elements correspond to enum test_flags::num args */ @@ -5599,10 +6057,10 @@ static test_loop_t float_loops[] = { NULL, NULL, &test_float_special, - NULL, - NULL, - NULL, - NULL, + &test_float_ld_one_reg_imm16, + &test_float_ld_two_regs, + &test_float_st_two_regs_imm16, + &test_float_st_three_regs, }; #endif /* !defined (NO_FLOAT) */