blob: 566f5c9767af0284f2252430f2a00ea8e7d6f143 [file] [log] [blame]
Elliott Hughesa0664b92017-04-18 17:46:52 -07001/*******************************************************************************
2 * Derived from the test case for the "dcbzl" instruction support by
3 * Dave Goodell * <goodell@mcs.anl.gov>
4 * (see: Bug 135264 - dcbzl instruction missing)
5 * and: coregrind/m_machine.c/find_ppc_dcbz_sz()
6 ******************************************************************************/
7
8/* ensure we have posix_memalign */
9#define _POSIX_C_SOURCE 200112L
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <string.h>
14#include <assert.h>
15
16static int query_block_size(void)
17{
18#define MAX_DCBZL_SZB (128) /* largest known effect of dcbzl */
19 char *test_block = NULL;
20 register char *rb asm ("r14");
21 int block_size, test_block_size = 4 * MAX_DCBZL_SZB, err;
22 char *p;
23
24 err = posix_memalign ((void **)&test_block, MAX_DCBZL_SZB, test_block_size);
25 if (err) {
26 fprintf(stderr, "posix_memalign() failed (err = %d [%s])\n", err, strerror(err));
27 return err;
28 }
29
30 rb = test_block;
31
32 memset(rb, 0xff, test_block_size);
33 asm volatile ("dcbzl 0, %[RB]" : : [RB] "r" (rb));
34 for (block_size = 0, p = rb; (p - rb) < test_block_size; p++)
35 if (!*p)
36 block_size++;
37 assert(block_size == 16 || block_size == 32 || block_size == 64 || block_size == 128);
38
39 free(test_block);
40 return block_size;
41}
42
43/* Test dcbzl at addr in buffer given dcbzl_block_size */
44static void test_dcbzl_at(char *addr, char *buffer, int block_size)
45{
46 int i;
47
48 /* Note: Assumption is that the length of buffer is three times the block_size. */
49 memset(buffer, 0xff, 3 * block_size);
50 asm volatile ("dcbzl %[RA], %[RB]" : : [RA] "r" (0), [RB] "r" (addr));
51 for (i = 0; i < block_size; i++) {
52 assert(buffer[i] == 0xff);
53 assert(buffer[block_size + i] == 0x00);
54 assert(buffer[2 * block_size + i] == 0xff);
55 }
56}
57
58/* Test for insn: dcbzl */
59static int test_dcbzl(void)
60{
61 int err;
62 char *buffer = NULL;
63 int buffer_size;
64 int block_size;
65
66 block_size = query_block_size();
67 assert(block_size == 16 || block_size == 32 || block_size == 64 || block_size == 128);
68 buffer_size = 3 * block_size;
69 err = posix_memalign((void **) &buffer, block_size, buffer_size);
70 if (err) {
71 fprintf(stderr, "posix_memalign() failed (err = %d [%s])\n", err, strerror(err));
72 return err;
73 }
74
75 /* check at aligned address within the test block */
76 test_dcbzl_at(&buffer[block_size], buffer, block_size);
77 fprintf(stdout, "Passed dcbzl test at aligned address within the test block.\n");
78
79 /* check at un-aligned (1 modulo block_size) address within the test block */
80 test_dcbzl_at(&buffer[block_size+1], buffer, block_size);
81 fprintf(stdout, "Passed dcbzl test at un-aligned (1 modulo block_size) address within the test block.\n");
82
83 /* check at un-aligned ((block_size - 1) modulo block_size) address within the test block */
84 test_dcbzl_at(&buffer[2 * block_size - 1], buffer, block_size);
85 fprintf(stdout, "Passed dcbzl test at un-aligned ((block_size - 1) modulo block_size) address within the test block.\n");
86
87 free(buffer);
88 return 0;
89}
90
91int main(int argc, char **argv)
92{
93 int status;
94 status = test_dcbzl ();
95 return status;
96}