1 /******************************************************************************* 2 * Derived from the test case for the "dcbzl" instruction support by 3 * Dave Goodell * <goodell (at) 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 16 static 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 */ 44 static 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 */ 59 static 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 91 int main(int argc, char **argv) 92 { 93 int status; 94 status = test_dcbzl (); 95 return status; 96 } 97