1  /* The z13 stpcpy implementation plays some alignment tricks for good
       2     performance.  This test tries to make sure it works correctly and
       3     does not access bytes beyond the source and destination
       4     strings.  */
       5  
       6  /* { dg-do run } */
       7  /* { dg-require-effective-target s390_vx } */
       8  /* { dg-options "-O3 -mzarch -march=z13" } */
       9  
      10  #include <stdio.h>
      11  #include <sys/mman.h>
      12  
      13  #define PAGE_SIZE 4096
      14  
      15  struct {
      16    char unused[PAGE_SIZE - 32];
      17    char m32[15]; /* page bndry - 32 */
      18    char m17[1];
      19    char m16[1];
      20    char m15[14];
      21    char m1[1];
      22    char next_page[PAGE_SIZE];
      23  } s, d __attribute__((aligned(PAGE_SIZE)));
      24  
      25  char *__attribute__((noinline))
      26  my_stpcpy(char *dest, const char *src)
      27  {
      28    return __builtin_stpcpy (dest, src);
      29  }
      30  
      31  void __attribute__ ((noinline))
      32  check (char *dest, char *src, size_t len)
      33  {
      34    char *result;
      35  
      36    result = my_stpcpy (dest, src);
      37    if (result != dest + len)
      38      __builtin_abort ();
      39    if (__builtin_memcmp (src, dest, len) != 0)
      40      __builtin_abort ();
      41  }
      42  
      43  int
      44  main ()
      45  {
      46    char *src[5] = { s.m32, s.m17, s.m16, s.m15, s.m1 };
      47    char *dst[5] = { d.m32, d.m17, d.m16, d.m15, d.m1 };
      48    int len[8] = { 33, 32, 31, 17, 16, 15, 1, 0 };
      49    int i, j, k;
      50    char backup;
      51  
      52    for (i = 0; i < sizeof (s); i++)
      53      ((char*)&s)[i] = i % 26 + 97;
      54  
      55    for (i = 0; i < 5; i++)
      56      for (j = 0; j < 5; j++)
      57        for (k = 0; k < 8; k++)
      58  	{
      59  	  backup = src[j][len[k]];
      60  	  src[j][len[k]] = 0;
      61  	  __builtin_memset (&d, 0, sizeof (d));
      62  	  check (dst[i], src[j], len[k]);
      63  	  src[j][len[k]] = backup;
      64  	}
      65  
      66    /* Make all source strings end before the page boundary.  */
      67    backup = s.m1[0];
      68    s.m1[0] = 0;
      69  
      70    if (mprotect (&s.next_page, PAGE_SIZE, PROT_NONE) == -1)
      71      perror ("mprotect src");
      72  
      73    for (i = 0; i < 5; i++)
      74      for (j = 0; j < 5; j++)
      75        check (dst[i], src[j],
      76  	     PAGE_SIZE - ((unsigned long)src[j] & ((1UL << 12) - 1)) - 1);
      77  
      78    if (mprotect (&s.next_page, PAGE_SIZE, PROT_READ | PROT_WRITE) == -1)
      79      perror ("mprotect src");
      80  
      81    s.m1[0] = backup;
      82  
      83    if (mprotect (&d.next_page, PAGE_SIZE, PROT_NONE) == -1)
      84      perror ("mprotect dst");
      85  
      86    for (i = 0; i < 5; i++)
      87      for (j = 0; j < 5; j++)
      88        {
      89  	int len = PAGE_SIZE - ((unsigned long)dst[i] & ((1UL << 12) - 1)) - 1;
      90  	char backup = src[j][len];
      91  
      92  	src[j][len] = 0;
      93  	__builtin_memset (&d, 0,
      94  			  (unsigned long)&d.next_page - (unsigned long)&d);
      95  	check (dst[i], src[j], len);
      96  	src[j][len] = backup;
      97        }
      98  
      99    return 0;
     100  }