1/*
2 * memcpy test.
3 *
4 * Copyright (c) 2019-2023, Arm Limited.
5 * SPDX-License-Identifier: MIT OR Apache-2.0 WITH LLVM-exception
6 */
7
8#include <stdint.h>
9#include <stdio.h>
10#include <stdlib.h>
11#include <string.h>
12#include "mte.h"
13#include "stringlib.h"
14#include "stringtest.h"
15
16#define F(x, mte) {#x, x, mte},
17
18static const struct fun
19{
20  const char *name;
21  void *(*fun) (void *, const void *, size_t);
22  int test_mte;
23} funtab[] = {
24  // clang-format off
25  F(memcpy, 0)
26#if __aarch64__
27  F(__memcpy_aarch64, 1)
28# if __ARM_NEON
29  F(__memcpy_aarch64_simd, 1)
30# endif
31# if __ARM_FEATURE_SVE
32  F(__memcpy_aarch64_sve, 1)
33# endif
34# if WANT_MOPS
35  F(__memcpy_aarch64_mops, 1)
36# endif
37#elif __arm__
38  F(__memcpy_arm, 0)
39#endif
40  {0, 0, 0}
41  // clang-format on
42};
43#undef F
44
45#define A 32
46#define LEN 250000
47static unsigned char *dbuf;
48static unsigned char *sbuf;
49static unsigned char wbuf[LEN + 2 * A];
50
51static void *
52alignup (void *p)
53{
54  return (void *) (((uintptr_t) p + A - 1) & -A);
55}
56
57static void
58test (const struct fun *fun, int dalign, int salign, int len)
59{
60  unsigned char *src = alignup (sbuf);
61  unsigned char *dst = alignup (dbuf);
62  unsigned char *want = wbuf;
63  unsigned char *s = src + salign;
64  unsigned char *d = dst + dalign;
65  unsigned char *w = want + dalign;
66  void *p;
67  int i;
68
69  if (err_count >= ERR_LIMIT)
70    return;
71  if (len > LEN || dalign >= A || salign >= A)
72    abort ();
73  for (i = 0; i < len + A; i++)
74    {
75      src[i] = '?';
76      want[i] = dst[i] = '*';
77    }
78  for (i = 0; i < len; i++)
79    s[i] = w[i] = 'a' + i % 23;
80
81  s = tag_buffer (s, len, fun->test_mte);
82  d = tag_buffer (d, len, fun->test_mte);
83  p = fun->fun (d, s, len);
84  untag_buffer (s, len, fun->test_mte);
85  untag_buffer (d, len, fun->test_mte);
86
87  if (p != d)
88    ERR ("%s(%p,..) returned %p\n", fun->name, d, p);
89  for (i = 0; i < len + A; i++)
90    {
91      if (dst[i] != want[i])
92	{
93	  ERR ("%s(align %d, align %d, %d) failed\n", fun->name, dalign, salign,
94	       len);
95	  quoteat ("got", dst, len + A, i);
96	  quoteat ("want", want, len + A, i);
97	  break;
98	}
99    }
100}
101
102int
103main ()
104{
105  dbuf = mte_mmap (LEN + 2 * A);
106  sbuf = mte_mmap (LEN + 2 * A);
107  int r = 0;
108  for (int i = 0; funtab[i].name; i++)
109    {
110      err_count = 0;
111      for (int d = 0; d < A; d++)
112	for (int s = 0; s < A; s++)
113	  {
114	    int n;
115	    for (n = 0; n < 100; n++)
116	      test (funtab + i, d, s, n);
117	    for (; n < LEN; n *= 2)
118	      test (funtab + i, d, s, n);
119	  }
120      char *pass = funtab[i].test_mte && mte_enabled () ? "MTE PASS" : "PASS";
121      printf ("%s %s\n", err_count ? "FAIL" : pass, funtab[i].name);
122      if (err_count)
123	r = -1;
124    }
125  return r;
126}
127