From 163762d1aa13a1c8fc230dfb53a41fb5a94f7468 Mon Sep 17 00:00:00 2001 From: Carl Love Date: Wed, 22 Apr 2015 21:17:48 +0000 Subject: [PATCH] There is an ABI change in how the PPC64 gcc compiler handles 128 bit arguments are aligned with GCC 5.0. The compiler generates a "note" about this starting with GCC 4.9. To avoid generating the "note", the passing of the arguments were changed to a pointer to make it pass by reference rather then pass by value. bugzilla 346487. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@15136 --- NEWS | 2 ++ none/tests/ppc32/test_dfp4.c | 53 ++++++++++++++++++------------- none/tests/ppc32/test_dfp5.c | 60 +++++++++++++++++++++++------------- 3 files changed, 72 insertions(+), 43 deletions(-) diff --git a/NEWS b/NEWS index 55ab227621..9fdc795250 100644 --- a/NEWS +++ b/NEWS @@ -164,6 +164,8 @@ n-i-bz (vex 3098) Avoid generation of Neon insns on non-Neon hosts 346416 Add support for LL_IOC_PATH2FID and LL_IOC_GETPARENT Lustre ioctls n-i-bz Enable rt_sigpending syscall on ppc64 linux. 346474 Added support for accessing the PPC64 TEXASRU register +346487 Change PPC64 function calls with 128-bit values to use a pointer so + the compiler will not generate a note about an ABI change. Release 3.10.1 (25 November 2014) diff --git a/none/tests/ppc32/test_dfp4.c b/none/tests/ppc32/test_dfp4.c index ebd39633a0..54ffbb0e86 100644 --- a/none/tests/ppc32/test_dfp4.c +++ b/none/tests/ppc32/test_dfp4.c @@ -93,9 +93,9 @@ typedef unsigned char Bool; * BF is the condition register bit field which can range from 0-7. But for * testing purposes, we only use BF values of '0' and '5'. */ -static void _test_dtstdc(int BF, int DCM, dfp_val_t val1, dfp_val_t x1 __attribute__((unused))) +static void _test_dtstdc(int BF, int DCM, dfp_val_t *val1, dfp_val_t *x1 __attribute__((unused))) { - _Decimal64 f14 = val1.dec_val; + _Decimal64 f14 = val1->dec_val; if (DCM < 0 || DCM > 5 || !(BF == 0 || BF == 5)) { fprintf(stderr, "Invalid inputs to asm test: a=%d, b=%d\n", BF, DCM); return; @@ -142,9 +142,9 @@ static void _test_dtstdc(int BF, int DCM, dfp_val_t val1, dfp_val_t x1 __attribu } } -static void _test_dtstdcq(int BF, int DCM, dfp_val_t val1, dfp_val_t x1 __attribute__((unused))) +static void _test_dtstdcq(int BF, int DCM, dfp_val_t *val1, dfp_val_t *x1 __attribute__((unused))) { - _Decimal128 f14 = val1.dec_val128; + _Decimal128 f14 = val1->dec_val128; if (DCM < 0 || DCM > 5 || !(BF == 0 || BF == 5)) { fprintf(stderr, "Invalid inputs to asm test: a=%d, b=%d\n", BF, DCM); return; @@ -197,9 +197,9 @@ static void _test_dtstdcq(int BF, int DCM, dfp_val_t val1, dfp_val_t x1 __attrib * BF is the condition register bit field which can range from 0-7. But for * testing purposes, we only use BF values of '0' and '5'. */ -static void _test_dtstdg(int BF, int DGM, dfp_val_t val1, dfp_val_t x1 __attribute__((unused))) +static void _test_dtstdg(int BF, int DGM, dfp_val_t *val1, dfp_val_t *x1 __attribute__((unused))) { - _Decimal64 f14 = val1.dec_val; + _Decimal64 f14 = val1->dec_val; if (DGM < 0 || DGM > 5 || !(BF == 0 || BF == 5)) { fprintf(stderr, "Invalid inputs to asm test: a=%d, b=%d\n", BF, DGM); return; @@ -246,9 +246,9 @@ static void _test_dtstdg(int BF, int DGM, dfp_val_t val1, dfp_val_t x1 __attribu } } -static void _test_dtstdgq(int BF, int DGM, dfp_val_t val1, dfp_val_t x1 __attribute__((unused))) +static void _test_dtstdgq(int BF, int DGM, dfp_val_t *val1, dfp_val_t *x1 __attribute__((unused))) { - _Decimal128 f14 = val1.dec_val128; + _Decimal128 f14 = val1->dec_val128; if (DGM < 0 || DGM > 5 || !(BF == 0 || BF == 5)) { fprintf(stderr, "Invalid inputs to asm test: a=%d, b=%d\n", BF, DGM); return; @@ -300,10 +300,10 @@ static void _test_dtstdgq(int BF, int DGM, dfp_val_t val1, dfp_val_t x1 __attrib * from 0-7, but for testing purposes, we only use BF values of '4' and '7'. */ static void -_test_dtstex(int BF, int x __attribute__((unused)), dfp_val_t val1, dfp_val_t val2) +_test_dtstex(int BF, int x __attribute__((unused)), dfp_val_t *val1, dfp_val_t *val2) { - _Decimal64 f14 = val1.dec_val; - _Decimal64 f16 = val2.dec_val; + _Decimal64 f14 = val1->dec_val; + _Decimal64 f16 = val2->dec_val; if (!(BF == 4 || BF == 7)) { fprintf(stderr, "Invalid input to asm test: a=%d\n", BF); return; @@ -320,10 +320,10 @@ _test_dtstex(int BF, int x __attribute__((unused)), dfp_val_t val1, dfp_val_t va } } -static void _test_dtstexq(int BF, int x __attribute__((unused)), dfp_val_t val1, dfp_val_t val2) +static void _test_dtstexq(int BF, int x __attribute__((unused)), dfp_val_t *val1, dfp_val_t *val2) { - _Decimal128 f14 = val1.dec_val128; - _Decimal128 f16 = val2.dec_val128; + _Decimal128 f14 = val1->dec_val128; + _Decimal128 f16 = val2->dec_val128; if (!(BF == 4 || BF == 7)) { fprintf(stderr, "Invalid input to asm test: a=%d\n", BF); return; @@ -342,7 +342,7 @@ static void _test_dtstexq(int BF, int x __attribute__((unused)), dfp_val_t val1, -typedef void (*test_func_t)(int a, int b, dfp_val_t val1, dfp_val_t val2); +typedef void (*test_funcp_t)(int a, int b, dfp_val_t *val1, dfp_val_t *val2); typedef void (*test_driver_func_t)(void); typedef struct test_table { @@ -454,7 +454,7 @@ typedef enum { typedef struct dfp_test { - test_func_t test_func; + test_funcp_t test_func; const char * name; dfp_test_args_t * targs; int num_tests; @@ -464,7 +464,7 @@ typedef struct dfp_test typedef struct dfp_one_arg_test { - test_func_t test_func; + test_funcp_t test_func; const char * name; precision_type_t precision; const char * op; @@ -483,7 +483,7 @@ dfp_ClassAndGroupTest_tests[] = { static void test_dfp_ClassAndGroupTest_ops(void) { - test_func_t func; + test_funcp_t func; dfp_val_t test_val, dummy; int k = 0; @@ -509,7 +509,13 @@ again: unsigned int flags; SET_FPSCR_ZERO; SET_CR_XER_ZERO; - (*func)(BF, data_class_OR_group, test_val, dummy); + + /* There is an ABI change in how 128 bit arguments are aligned + * with GCC 5.0. The compiler generates a "note" about this + * starting with GCC 4.8. To avoid generating the "note", pass + * the address of the 128-bit arguments rather then the value. + */ + (*func)(BF, data_class_OR_group, &test_val, &dummy); GET_CR(flags); condreg = ((flags >> (4 * (7-BF)))) & 0xf; @@ -547,7 +553,7 @@ dfp_ExpTest_tests[] = { static void test_dfp_ExpTest_ops(void) { dfp_val_t test_val1, test_val2; - test_func_t func; + test_funcp_t func; int k = 0; while ((func = dfp_ExpTest_tests[k].test_func)) { @@ -577,7 +583,12 @@ again: SET_FPSCR_ZERO; SET_CR_XER_ZERO; - (*func)(BF, 0, test_val1, test_val2); + /* There is an ABI change in how 128 bit arguments are aligned + * with GCC 5.0. The compiler generates a "note" about this + * starting with GCC 4.8. To avoid generating the "note", pass + * the address of the 128-bit arguments rather then the value. + */ + (*func)(BF, 0, &test_val1, &test_val2); GET_CR(flags); condreg = ((flags >> (4 * (7-BF)))) & 0xf; diff --git a/none/tests/ppc32/test_dfp5.c b/none/tests/ppc32/test_dfp5.c index d8122d896e..b00573f2e8 100644 --- a/none/tests/ppc32/test_dfp5.c +++ b/none/tests/ppc32/test_dfp5.c @@ -93,9 +93,9 @@ typedef uint64_t HWord_t; enum BF_vals { BF_val1 = 0, BF_val2 = 1, BF_val3 =6}; // The assembly-level instructions being tested -static void _test_dtstsf(unsigned int BF, unsigned int ref_sig, dfp_val_t valB) +static void _test_dtstsf(unsigned int BF, unsigned int ref_sig, dfp_val_t *valB) { - _Decimal64 f16 = valB.dec_val; + _Decimal64 f16 = valB->dec_val; register HWord_t r14 __asm__ ("r14"); double f14; r14 = (HWord_t)&ref_sig; @@ -117,9 +117,9 @@ static void _test_dtstsf(unsigned int BF, unsigned int ref_sig, dfp_val_t valB) } } -static void _test_dtstsfq(unsigned int BF, unsigned int ref_sig, dfp_val_t valB) +static void _test_dtstsfq(unsigned int BF, unsigned int ref_sig, dfp_val_t *valB) { - _Decimal128 f16 = valB.dec_val128; + _Decimal128 f16 = valB->dec_val128; register HWord_t r14 __asm__ ("r14"); double f14; r14 = (HWord_t)&ref_sig; @@ -141,11 +141,11 @@ static void _test_dtstsfq(unsigned int BF, unsigned int ref_sig, dfp_val_t valB) } } -static dfp_val_t _test_ddedpd(unsigned int SP, dfp_val_t valB) +static dfp_val_t _test_ddedpd(unsigned int SP, dfp_val_t *valB) { _Decimal64 ret = 0; dfp_val_t result; - _Decimal64 f16 = valB.dec_val; + _Decimal64 f16 = valB->dec_val; switch (SP) { case 0: __asm__ __volatile__ ("ddedpd. 0, %0, %1" : "=f" (ret) : "f" (f16)); @@ -168,11 +168,11 @@ static dfp_val_t _test_ddedpd(unsigned int SP, dfp_val_t valB) } -static dfp_val_t _test_ddedpdq(unsigned int SP, dfp_val_t valB) +static dfp_val_t _test_ddedpdq(unsigned int SP, dfp_val_t *valB) { _Decimal128 ret = 0; dfp_val_t result; - _Decimal128 f16 = valB.dec_val128; + _Decimal128 f16 = valB->dec_val128; switch (SP) { case 0: __asm__ __volatile__ ("ddedpdq 0, %0, %1" : "=f" (ret) : "f" (f16)); @@ -194,11 +194,11 @@ static dfp_val_t _test_ddedpdq(unsigned int SP, dfp_val_t valB) return result; } -static dfp_val_t _test_denbcd(unsigned int S, dfp_val_t valB) +static dfp_val_t _test_denbcd(unsigned int S, dfp_val_t *valB) { _Decimal64 ret = 0; dfp_val_t result; - _Decimal64 f16 = valB.dec_val; + _Decimal64 f16 = valB->dec_val; switch (S) { case 0: __asm__ __volatile__ ("denbcd. 0, %0, %1" : "=f" (ret) : "f" (f16)); @@ -215,11 +215,11 @@ static dfp_val_t _test_denbcd(unsigned int S, dfp_val_t valB) } -static dfp_val_t _test_denbcdq(unsigned int S, dfp_val_t valB) +static dfp_val_t _test_denbcdq(unsigned int S, dfp_val_t *valB) { _Decimal128 ret = 0; dfp_val_t result; - _Decimal128 f16 = valB.dec_val128; + _Decimal128 f16 = valB->dec_val128; switch (S) { case 0: __asm__ __volatile__ ("denbcdq 0, %0, %1" : "=f" (ret) : "f" (f16)); @@ -236,8 +236,8 @@ static dfp_val_t _test_denbcdq(unsigned int S, dfp_val_t valB) } -typedef void (*test_func_t)(unsigned int imm, unsigned int imm2, dfp_val_t valB); -typedef dfp_val_t (*test_func_bcd_t)(unsigned int imm, dfp_val_t valB); +typedef void (*test_funcp_t)(unsigned int imm, unsigned int imm2, dfp_val_t *valB); +typedef dfp_val_t (*test_func_bcdp_t)(unsigned int imm, dfp_val_t *valB); typedef void (*test_driver_func_t)(void); typedef struct test_table { @@ -384,7 +384,7 @@ typedef enum { typedef struct dfp_one_arg_test { - test_func_t test_func; + test_funcp_t test_func; const char * name; precision_type_t precision; const char * op; @@ -392,7 +392,7 @@ typedef struct dfp_one_arg_test typedef struct dfp_one_arg_bcd_test { - test_func_bcd_t test_func; + test_func_bcdp_t test_func; const char * name; precision_type_t precision; const char * op; @@ -407,7 +407,7 @@ dfp_test_dfp_ddedpd_tests[] = { static void test_dfp_ddedpd_ops(void) { - test_func_bcd_t func; + test_func_bcdp_t func; dfp_val_t test_val; int k = 0; @@ -428,7 +428,13 @@ static void test_dfp_ddedpd_ops(void) for (SP = 0; SP < 4; SP++) { dfp_val_t result; - result = (*func)(SP, test_val); + + /* There is an ABI change in how 128 bit arguments are aligned + * with GCC 5.0. The compiler generates a "note" about this + * starting with GCC 4.8. To avoid generating the "note", pass + * the address of the 128-bit arguments rather then the value. + */ + result = (*func)(SP, &test_val); printf("%s (SP=%d) %s", test_def.name, SP, test_def.op); if (test_def.precision == LONG_TEST) { printf("%016llx ==> %016llx\n", test_val.u64_val, result.u64_val); @@ -453,7 +459,7 @@ dfp_test_dfp_denbcd_tests[] = { static void test_dfp_denbcd_ops(void) { - test_func_bcd_t func; + test_func_bcdp_t func; dfp_val_t test_val; int num_test_vals; @@ -490,7 +496,12 @@ static void test_dfp_denbcd_ops(void) test_val.u128.vall = bcd128_vals[(i * 2) + 1]; } - result = (*func)(S, test_val); + /* There is an API change in how 128 bit arguments are aligned + * with GCC 5.0. The compiler generates a "note" about this + * starting with GCC 4.8. To avoid generating the "note", pass + * the address of the 128-bit arguments rather then the value. + */ + result = (*func)(S, &test_val); printf("%s (S=%d) %s", test_def.name, S, test_def.op); if (test_def.precision == LONG_TEST) { printf("%016llx ==> %016llx\n", test_val.u64_val, result.u64_val); @@ -516,7 +527,7 @@ dfp_test_significance_tests[] = { static void test_dfp_test_significance_ops(void) { - test_func_t func; + test_funcp_t func; dfp_val_t test_valB; int k = 0; unsigned int BF_vals[] = {BF_val1, BF_val2, BF_val3}; @@ -545,7 +556,12 @@ static void test_dfp_test_significance_ops(void) BF = BF_vals[bf_idx]; SET_FPSCR_ZERO; SET_CR_XER_ZERO; - (*func)(BF, reference_sig, test_valB); + /* There is an ABI change in how 128 bit arguments are aligned + * with GCC 5.0. The compiler generates a "note" about this + * starting with GCC 4.9. To avoid generating the "note", pass + * the address of the 128-bit arguments rather then the value. + */ + (*func)(BF, reference_sig, &test_valB); GET_CR(flags); condreg = ((flags >> (4 * (7-BF)))) & 0xf; -- 2.47.3