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 vector } */
8/* { dg-options "-O3 -mzarch -march=z13" } */
9
10#include <stdio.h>
11#include <sys/mman.h>
12
13#define PAGE_SIZE 4096
14
15struct {
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
25char *__attribute__((noinline))
26my_stpcpy(char *dest, const char *src)
27{
28  return __builtin_stpcpy (dest, src);
29}
30
31void __attribute__ ((noinline))
32check (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
43int
44main ()
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}
101