1 | // REQUIRES: aarch64-target-arch, aarch64-sme-available |
2 | // RUN: %clangxx_builtins %s %librt -o %t && %run %t |
3 | |
4 | #include <cassert> |
5 | #include <initializer_list> |
6 | #include <stdint.h> |
7 | #include <stdlib.h> |
8 | #include <string.h> |
9 | |
10 | extern "C" { |
11 | void *__arm_sc_memcpy(void *, const void *, size_t); |
12 | void *__arm_sc_memset(void *, int, size_t); |
13 | void *__arm_sc_memmove(void *, const void *, size_t); |
14 | void *__arm_sc_memchr(const void *, int, size_t); |
15 | } |
16 | |
17 | template <unsigned N> class Memory { |
18 | public: |
19 | uint8_t ptr[N]; |
20 | unsigned size; |
21 | |
22 | Memory(unsigned stride = 0) { |
23 | size = N; |
24 | if (stride == 0) |
25 | return; |
26 | for (unsigned i = 0; i < N; i++) |
27 | ptr[i] = i * stride; |
28 | } |
29 | |
30 | void assert_equal(const Memory &other) { |
31 | assert(N == other.size); |
32 | assert(memcmp(ptr, other.ptr, N) == 0); |
33 | } |
34 | |
35 | void assert_equal(std::initializer_list<uint8_t> s) { |
36 | assert(N == s.size()); |
37 | auto it = s.begin(); |
38 | for (unsigned i = 0; i < N; ++i) |
39 | assert(ptr[i] == *it++); |
40 | } |
41 | |
42 | void assert_elemt_equal_at(unsigned I, uint8_t elem) { |
43 | assert(ptr[I] == elem); |
44 | } |
45 | }; |
46 | |
47 | int main() { |
48 | |
49 | // Testing memcpy from src to dst. |
50 | { |
51 | Memory<8> src(1); |
52 | Memory<8> dst; |
53 | if (!__arm_sc_memcpy(dst.ptr, src.ptr, 8)) |
54 | abort(); |
55 | dst.assert_equal(other: src); |
56 | dst.assert_equal(s: {0, 1, 2, 3, 4, 5, 6, 7}); |
57 | } |
58 | |
59 | // Testing memcpy from src to dst with pointer offset. |
60 | { |
61 | Memory<8> src(1); |
62 | Memory<8> dst(1); |
63 | if (!__arm_sc_memcpy(dst.ptr + 1, src.ptr, 6)) |
64 | abort(); |
65 | dst.assert_equal(s: {0, 0, 1, 2, 3, 4, 5, 7}); |
66 | } |
67 | |
68 | // Testing memchr. |
69 | { |
70 | Memory<8> src(4); |
71 | for (unsigned i = 0; i < 8; ++i) { |
72 | uint8_t e = src.ptr[i]; |
73 | uint8_t *elem = (uint8_t *)memchr(s: src.ptr, c: e, n: 8); |
74 | if (!elem) |
75 | abort(); |
76 | src.assert_elemt_equal_at(I: elem - src.ptr, elem: *elem); |
77 | for (unsigned i = 0; i < 8; ++i) |
78 | assert(__arm_sc_memchr(src.ptr, src.ptr[i], 8) == |
79 | memchr(src.ptr, src.ptr[i], 8)); |
80 | } |
81 | } |
82 | |
83 | // Testing memset. |
84 | { |
85 | Memory<8> array; |
86 | if (!__arm_sc_memset(array.ptr, 2, 8)) |
87 | abort(); |
88 | array.assert_equal(s: {2, 2, 2, 2, 2, 2, 2, 2}); |
89 | } |
90 | |
91 | // Testing memset with pointer offset. |
92 | { |
93 | Memory<8> array(1); |
94 | if (!__arm_sc_memset(array.ptr + 1, 2, 6)) |
95 | abort(); |
96 | array.assert_equal(s: {0, 2, 2, 2, 2, 2, 2, 7}); |
97 | } |
98 | |
99 | // Testing memmove with a simple non-overlap case. |
100 | { |
101 | Memory<8> src(1); |
102 | Memory<8> dst(1); |
103 | if (!__arm_sc_memmove(dst.ptr + 1, src.ptr, 6)) |
104 | abort(); |
105 | dst.assert_equal(s: {0, 0, 1, 2, 3, 4, 5, 7}); |
106 | } |
107 | |
108 | // Testing memove with overlap pointers dst > src, dst < src. |
109 | { |
110 | Memory<8> srcdst(1); |
111 | if (!__arm_sc_memmove(srcdst.ptr + 1, srcdst.ptr, 6)) |
112 | abort(); |
113 | srcdst.assert_equal(s: {0, 0, 1, 2, 3, 4, 5, 7}); |
114 | if (!__arm_sc_memmove(srcdst.ptr, srcdst.ptr + 1, 6)) |
115 | abort(); |
116 | srcdst.assert_equal(s: {0, 1, 2, 3, 4, 5, 5, 7}); |
117 | } |
118 | |
119 | return 0; |
120 | } |
121 | |