Home | History | Annotate | Download | only in ppc32
      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