From: Carl Love Date: Sat, 8 Feb 2014 02:19:12 +0000 (+0000) Subject: This commit is a fix for "Bug 330622 - Add test to regression suite for POWER X-Git-Tag: svn/VALGRIND_3_10_0~645 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=49987d5c4a2704149de1355d304a553ecabea142;p=thirdparty%2Fvalgrind.git This commit is a fix for "Bug 330622 - Add test to regression suite for POWER instruction: dcbzl" submitted by Anmol P. Paralkar The patch adds the following files: none/tests/ppc64/data-cache-instructions.vgtest none/tests/ppc64/data-cache-instructions.c none/tests/ppc64/data-cache-instructions.stdout.exp none/tests/ppc64/data-cache-instructions.stderr.exp none/tests/ppc32/data-cache-instructions.stdout.exp none/tests/ppc32/data-cache-instructions.c none/tests/ppc32/data-cache-instructions.vgtest none/tests/ppc32/data-cache-instructions.stderr.exp tests/power_insn_available.c The following files are modified: none/tests/ppc32/Makefile.am none/tests/ppc64/Makefile.am tests/Makefile.am git-svn-id: svn://svn.valgrind.org/valgrind/trunk@13791 --- diff --git a/none/tests/ppc32/Makefile.am b/none/tests/ppc32/Makefile.am index 08486cdcc4..5b3fef9832 100644 --- a/none/tests/ppc32/Makefile.am +++ b/none/tests/ppc32/Makefile.am @@ -44,7 +44,8 @@ EXTRA_DIST = \ test_isa_2_07_part2.stderr.exp test_isa_2_07_part2.stdout.exp test_isa_2_07_part2.vgtest \ test_tm.stderr.exp test_tm.stdout.exp test_tm.vgtest \ test_touch_tm.stderr.exp test_touch_tm.stdout.exp test_touch_tm.vgtest \ - ldst_multiple.stderr.exp ldst_multiple.stdout.exp ldst_multiple.vgtest + ldst_multiple.stderr.exp ldst_multiple.stdout.exp ldst_multiple.vgtest \ + data-cache-instructions.stderr.exp data-cache-instructions.stdout.exp data-cache-instructions.vgtest check_PROGRAMS = \ @@ -61,7 +62,8 @@ check_PROGRAMS = \ test_isa_2_07_part2 \ test_tm \ test_touch_tm \ - ldst_multiple + ldst_multiple \ + data-cache-instructions AM_CFLAGS += @FLAG_M32@ AM_CXXFLAGS += @FLAG_M32@ diff --git a/none/tests/ppc32/data-cache-instructions.c b/none/tests/ppc32/data-cache-instructions.c new file mode 100644 index 0000000000..566f5c9767 --- /dev/null +++ b/none/tests/ppc32/data-cache-instructions.c @@ -0,0 +1,96 @@ +/******************************************************************************* + * Derived from the test case for the "dcbzl" instruction support by + * Dave Goodell * + * (see: Bug 135264 - dcbzl instruction missing) + * and: coregrind/m_machine.c/find_ppc_dcbz_sz() + ******************************************************************************/ + +/* ensure we have posix_memalign */ +#define _POSIX_C_SOURCE 200112L + +#include +#include +#include +#include + +static int query_block_size(void) +{ +#define MAX_DCBZL_SZB (128) /* largest known effect of dcbzl */ + char *test_block = NULL; + register char *rb asm ("r14"); + int block_size, test_block_size = 4 * MAX_DCBZL_SZB, err; + char *p; + + err = posix_memalign ((void **)&test_block, MAX_DCBZL_SZB, test_block_size); + if (err) { + fprintf(stderr, "posix_memalign() failed (err = %d [%s])\n", err, strerror(err)); + return err; + } + + rb = test_block; + + memset(rb, 0xff, test_block_size); + asm volatile ("dcbzl 0, %[RB]" : : [RB] "r" (rb)); + for (block_size = 0, p = rb; (p - rb) < test_block_size; p++) + if (!*p) + block_size++; + assert(block_size == 16 || block_size == 32 || block_size == 64 || block_size == 128); + + free(test_block); + return block_size; +} + +/* Test dcbzl at addr in buffer given dcbzl_block_size */ +static void test_dcbzl_at(char *addr, char *buffer, int block_size) +{ + int i; + + /* Note: Assumption is that the length of buffer is three times the block_size. */ + memset(buffer, 0xff, 3 * block_size); + asm volatile ("dcbzl %[RA], %[RB]" : : [RA] "r" (0), [RB] "r" (addr)); + for (i = 0; i < block_size; i++) { + assert(buffer[i] == 0xff); + assert(buffer[block_size + i] == 0x00); + assert(buffer[2 * block_size + i] == 0xff); + } +} + +/* Test for insn: dcbzl */ +static int test_dcbzl(void) +{ + int err; + char *buffer = NULL; + int buffer_size; + int block_size; + + block_size = query_block_size(); + assert(block_size == 16 || block_size == 32 || block_size == 64 || block_size == 128); + buffer_size = 3 * block_size; + err = posix_memalign((void **) &buffer, block_size, buffer_size); + if (err) { + fprintf(stderr, "posix_memalign() failed (err = %d [%s])\n", err, strerror(err)); + return err; + } + + /* check at aligned address within the test block */ + test_dcbzl_at(&buffer[block_size], buffer, block_size); + fprintf(stdout, "Passed dcbzl test at aligned address within the test block.\n"); + + /* check at un-aligned (1 modulo block_size) address within the test block */ + test_dcbzl_at(&buffer[block_size+1], buffer, block_size); + fprintf(stdout, "Passed dcbzl test at un-aligned (1 modulo block_size) address within the test block.\n"); + + /* check at un-aligned ((block_size - 1) modulo block_size) address within the test block */ + test_dcbzl_at(&buffer[2 * block_size - 1], buffer, block_size); + fprintf(stdout, "Passed dcbzl test at un-aligned ((block_size - 1) modulo block_size) address within the test block.\n"); + + free(buffer); + return 0; +} + +int main(int argc, char **argv) +{ + int status; + status = test_dcbzl (); + return status; +} diff --git a/none/tests/ppc32/data-cache-instructions.stderr.exp b/none/tests/ppc32/data-cache-instructions.stderr.exp new file mode 100644 index 0000000000..139597f9cb --- /dev/null +++ b/none/tests/ppc32/data-cache-instructions.stderr.exp @@ -0,0 +1,2 @@ + + diff --git a/none/tests/ppc32/data-cache-instructions.stdout.exp b/none/tests/ppc32/data-cache-instructions.stdout.exp new file mode 100644 index 0000000000..bf98e13cd5 --- /dev/null +++ b/none/tests/ppc32/data-cache-instructions.stdout.exp @@ -0,0 +1,3 @@ +Passed dcbzl test at aligned address within the test block. +Passed dcbzl test at un-aligned (1 modulo block_size) address within the test block. +Passed dcbzl test at un-aligned ((block_size - 1) modulo block_size) address within the test block. diff --git a/none/tests/ppc32/data-cache-instructions.vgtest b/none/tests/ppc32/data-cache-instructions.vgtest new file mode 100644 index 0000000000..42a3b311bf --- /dev/null +++ b/none/tests/ppc32/data-cache-instructions.vgtest @@ -0,0 +1,2 @@ +prereq: ../../../tests/power_insn_available dcbzl +prog: data-cache-instructions diff --git a/none/tests/ppc64/Makefile.am b/none/tests/ppc64/Makefile.am index fc43f081a2..20a2ebb3df 100644 --- a/none/tests/ppc64/Makefile.am +++ b/none/tests/ppc64/Makefile.am @@ -32,7 +32,8 @@ EXTRA_DIST = \ test_isa_2_07_part2.stderr.exp test_isa_2_07_part2.stdout.exp test_isa_2_07_part2.vgtest \ test_tm.stderr.exp test_tm.stdout.exp test_tm.vgtest \ test_touch_tm.stderr.exp test_touch_tm.stdout.exp test_touch_tm.vgtest \ - ldst_multiple.stderr.exp ldst_multiple.stdout.exp ldst_multiple.vgtest + ldst_multiple.stderr.exp ldst_multiple.stdout.exp ldst_multiple.vgtest \ + data-cache-instructions.stderr.exp data-cache-instructions.stdout.exp data-cache-instructions.vgtest check_PROGRAMS = \ allexec \ @@ -40,7 +41,7 @@ check_PROGRAMS = \ power6_mf_gpr test_isa_2_06_part1 test_isa_2_06_part2 \ test_isa_2_06_part3 test_dfp1 test_dfp2 test_dfp3 test_dfp4 \ test_dfp5 test_isa_2_07_part1 test_isa_2_07_part2 \ - test_tm test_touch_tm ldst_multiple + test_tm test_touch_tm ldst_multiple data-cache-instructions AM_CFLAGS += @FLAG_M64@ AM_CXXFLAGS += @FLAG_M64@ diff --git a/none/tests/ppc64/data-cache-instructions.c b/none/tests/ppc64/data-cache-instructions.c new file mode 120000 index 0000000000..d2b3df060d --- /dev/null +++ b/none/tests/ppc64/data-cache-instructions.c @@ -0,0 +1 @@ +../ppc32/data-cache-instructions.c \ No newline at end of file diff --git a/none/tests/ppc64/data-cache-instructions.stderr.exp b/none/tests/ppc64/data-cache-instructions.stderr.exp new file mode 100644 index 0000000000..139597f9cb --- /dev/null +++ b/none/tests/ppc64/data-cache-instructions.stderr.exp @@ -0,0 +1,2 @@ + + diff --git a/none/tests/ppc64/data-cache-instructions.stdout.exp b/none/tests/ppc64/data-cache-instructions.stdout.exp new file mode 100644 index 0000000000..bf98e13cd5 --- /dev/null +++ b/none/tests/ppc64/data-cache-instructions.stdout.exp @@ -0,0 +1,3 @@ +Passed dcbzl test at aligned address within the test block. +Passed dcbzl test at un-aligned (1 modulo block_size) address within the test block. +Passed dcbzl test at un-aligned ((block_size - 1) modulo block_size) address within the test block. diff --git a/none/tests/ppc64/data-cache-instructions.vgtest b/none/tests/ppc64/data-cache-instructions.vgtest new file mode 100644 index 0000000000..42a3b311bf --- /dev/null +++ b/none/tests/ppc64/data-cache-instructions.vgtest @@ -0,0 +1,2 @@ +prereq: ../../../tests/power_insn_available dcbzl +prog: data-cache-instructions diff --git a/tests/Makefile.am b/tests/Makefile.am index 974f0a599f..adfbec4564 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -30,7 +30,8 @@ check_PROGRAMS = \ true \ x86_amd64_features \ s390x_features \ - mips_features + mips_features \ + power_insn_available AM_CFLAGS += $(AM_FLAG_M3264_PRI) AM_CXXFLAGS += $(AM_FLAG_M3264_PRI) diff --git a/tests/power_insn_available.c b/tests/power_insn_available.c new file mode 100644 index 0000000000..1bfea2a91a --- /dev/null +++ b/tests/power_insn_available.c @@ -0,0 +1,92 @@ +#include +#include +#include +#include +#include +#include + +typedef enum exit_codes_ { + +#if defined(VGA_ppc32) || defined(VGA_ppc64) + /* If the insn that got queried for: exists */ + POWER_INSN_AVAILABLE = 0, + /* If the insn that got queried for: does not exist on this platform */ + POWER_INSN_UNAVAILABLE = 1, + /* If the insn that got queried for: does not exist in the vocabulary of this program */ + POWER_INSN_UNRECOGNIZED = 2, + + /* Note: Please keep USAGE_ERROR last. */ + USAGE_ERROR +#else + /* When not on a POWER system: */ + NOT_POWER_ARCH = 255, +#endif + +} exit_code; + +#if defined(VGA_ppc32) || defined(VGA_ppc64) +/* Signal Handling support for unsupported instructions. */ +static jmp_buf unsup_insn_env; +static void unsup_insn_handler(int signal_number) +{ + if (signal_number == SIGILL) + longjmp(unsup_insn_env, 1); + return; +} +static struct sigaction unsup_insn_action = (struct sigaction) { + .sa_handler = &unsup_insn_handler, +}; + +/* Instruction existence tests. */ +static bool dcbzl_available(void) +{ +#define MAX_DCBZL_SZB (128) /* largest known effect of dcbzl */ + char *test_block = NULL; + register char *rb asm ("r14"); + int err; + bool dcbzl_exists = false; + + err = posix_memalign ((void **)&test_block, MAX_DCBZL_SZB, 4 * MAX_DCBZL_SZB); + if (err) { + fprintf(stderr, "posix_memalign() failed (err = %d [%s])\n", err, strerror(err)); + return err; + } + + rb = test_block; + + if (setjmp(unsup_insn_env) != 0) + dcbzl_exists = false; + else { + sigaction(SIGILL, &unsup_insn_action, NULL); + asm volatile ("dcbzl 0, %[RB]" : : [RB] "r" (rb)); + dcbzl_exists = true; + } + + free(test_block); + return dcbzl_exists; +} +#endif + +/* main() */ +int main(int argc, char **argv) +{ + exit_code status; + +#if defined(VGA_ppc32) || defined(VGA_ppc64) + char *insn; + if (argc != 2) { + fprintf(stderr, "usage: power_insn_available \n" ); + exit(USAGE_ERROR); + } + + insn = argv[1]; + if (strcmp (insn, "dcbzl") == 0) + status = ((dcbzl_available ()) ? POWER_INSN_AVAILABLE : POWER_INSN_UNAVAILABLE); + else + /* power_insn_available has not been taught anything about this insn yet. */ + status = POWER_INSN_UNRECOGNIZED; +#else + status = NOT_POWER_ARCH; +#endif + return status; +}