115379797d2429dee3e8ad278c02ead53799c9a3
[vpp.git] / src / vppinfra / memcpy.h
1 /* SPDX-License-Identifier: Apache-2.0
2  * Copyright(c) 2021 Cisco Systems, Inc.
3  */
4
5 #include <vppinfra/clib.h>
6 #ifndef included_memcpy_h
7 #define included_memcpy_h
8
9 static_always_inline void
10 clib_memcpy_u32_x4 (u32 *dst, u32 *src)
11 {
12 #if defined(CLIB_HAVE_VEC128)
13   u32x4_store_unaligned (u32x4_load_unaligned (src), dst);
14 #else
15   clib_memcpy_fast (dst, src, 4 * sizeof (u32));
16 #endif
17 }
18 static_always_inline void
19 clib_memcpy_u32_x8 (u32 *dst, u32 *src)
20 {
21 #if defined(CLIB_HAVE_VEC256)
22   u32x8_store_unaligned (u32x8_load_unaligned (src), dst);
23 #else
24   clib_memcpy_u32_x4 (dst, src);
25   clib_memcpy_u32_x4 (dst + 4, src + 4);
26 #endif
27 }
28
29 static_always_inline void
30 clib_memcpy_u32_x16 (u32 *dst, u32 *src)
31 {
32 #if defined(CLIB_HAVE_VEC512)
33   u32x16_store_unaligned (u32x16_load_unaligned (src), dst);
34 #else
35   clib_memcpy_u32_x8 (dst, src);
36   clib_memcpy_u32_x8 (dst + 8, src + 8);
37 #endif
38 }
39
40 static_always_inline void
41 clib_memcpy_u32 (u32 *dst, u32 *src, u32 n_left)
42 {
43 #if defined(CLIB_HAVE_VEC128)
44   if (COMPILE_TIME_CONST (n_left))
45     {
46       /* for n_left defined as compile-time constant we should prevent compiler
47        * to use more expensive mask load/store for common cases where smaller
48        * register load/store exists */
49       switch (n_left)
50         {
51         case 4:
52           clib_memcpy_u32_x4 (dst, src);
53           return;
54         case 8:
55           clib_memcpy_u32_x8 (dst, src);
56           return;
57         case 12:
58           clib_memcpy_u32_x8 (dst, src);
59           clib_memcpy_u32_x4 (dst + 8, src + 8);
60           return;
61         case 16:
62           clib_memcpy_u32_x16 (dst, src);
63           return;
64         case 32:
65           clib_memcpy_u32_x16 (dst, src);
66           clib_memcpy_u32_x16 (dst + 16, src + 16);
67           return;
68         case 64:
69           clib_memcpy_u32_x16 (dst, src);
70           clib_memcpy_u32_x16 (dst + 16, src + 16);
71           clib_memcpy_u32_x16 (dst + 32, src + 32);
72           clib_memcpy_u32_x16 (dst + 48, src + 48);
73           return;
74         default:
75           break;
76         }
77     }
78
79 #if defined(CLIB_HAVE_VEC512)
80   while (n_left >= 64)
81     {
82       clib_memcpy_u32_x16 (dst, src);
83       clib_memcpy_u32_x16 (dst + 16, src + 16);
84       clib_memcpy_u32_x16 (dst + 32, src + 32);
85       clib_memcpy_u32_x16 (dst + 48, src + 48);
86       dst += 64;
87       src += 64;
88       n_left -= 64;
89     }
90 #endif
91
92 #if defined(CLIB_HAVE_VEC256)
93   while (n_left >= 32)
94     {
95       clib_memcpy_u32_x16 (dst, src);
96       clib_memcpy_u32_x16 (dst + 16, src + 16);
97       dst += 32;
98       src += 32;
99       n_left -= 32;
100     }
101 #endif
102
103   while (n_left >= 16)
104     {
105       clib_memcpy_u32_x16 (dst, src);
106       dst += 16;
107       src += 16;
108       n_left -= 16;
109     }
110
111 #if defined(CLIB_HAVE_VEC512_MASK_LOAD_STORE)
112   if (n_left)
113     {
114       u16 mask = pow2_mask (n_left);
115       u32x16_mask_store (u32x16_mask_load_zero (src, mask), dst, mask);
116     }
117   return;
118 #endif
119
120   if (n_left >= 8)
121     {
122       clib_memcpy_u32_x8 (dst, src);
123       dst += 8;
124       src += 8;
125       n_left -= 8;
126     }
127
128 #if defined(CLIB_HAVE_VEC256_MASK_LOAD_STORE)
129   if (n_left)
130     {
131       u8 mask = pow2_mask (n_left);
132       u32x8_mask_store (u32x8_mask_load_zero (src, mask), dst, mask);
133     }
134   return;
135 #endif
136
137   if (n_left >= 4)
138     {
139       clib_memcpy_u32_x4 (dst, src);
140       dst += 4;
141       src += 4;
142       n_left -= 4;
143     }
144 #endif
145
146   while (n_left)
147     {
148       dst[0] = src[0];
149       dst += 1;
150       src += 1;
151       n_left -= 1;
152     }
153 }
154
155 #endif