1 //===-- Elementary operations for aarch64 ---------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef LLVM_LIBC_SRC_STRING_MEMORY_UTILS_BACKEND_AARCH64_H
10 #define LLVM_LIBC_SRC_STRING_MEMORY_UTILS_BACKEND_AARCH64_H
11
12 #if !defined(LLVM_LIBC_ARCH_AARCH64)
13 #include "src/string/memory_utils/backend_scalar.h"
14
15 #ifdef __ARM_NEON
16 #include <arm_neon.h>
17 #endif
18
19 namespace __llvm_libc {
20
21 struct Aarch64Backend : public Scalar64BitBackend {
22 static constexpr bool IS_BACKEND_TYPE = true;
23
24 template <typename T, Temporality TS, Aligned AS,
25 cpp::EnableIfType<Scalar64BitBackend::IsScalarType<T>, bool> = true>
loadAarch64Backend26 static inline T load(const T *src) {
27 return Scalar64BitBackend::template load<T, TS, AS>(src);
28 }
29 };
30
31 // Implementation of the SizedOp abstraction for the set operation.
32 struct Zva64 {
33 static constexpr size_t SIZE = 64;
34
35 template <typename DstAddrT>
setZva6436 static inline void set(DstAddrT dst, ubyte value) {
37 #if __SIZEOF_POINTER__ == 4
38 asm("dc zva, %w[dst]" : : [dst] "r"(dst) : "memory");
39 #else
40 asm("dc zva, %[dst]" : : [dst] "r"(dst) : "memory");
41 #endif
42 }
43 };
44
hasZva()45 inline static bool hasZva() {
46 uint64_t zva_val;
47 asm("mrs %[zva_val], dczid_el0" : [zva_val] "=r"(zva_val));
48 // DC ZVA is permitted if DZP, bit [4] is zero.
49 // BS, bits [3:0] is log2 of the block size in words.
50 // So the next line checks whether the instruction is permitted and block size
51 // is 16 words (i.e. 64 bytes).
52 return (zva_val & 0b11111) == 0b00100;
53 }
54
55 namespace aarch64 {
56 using _1 = SizedOp<Aarch64Backend, 1>;
57 using _2 = SizedOp<Aarch64Backend, 2>;
58 using _3 = SizedOp<Aarch64Backend, 3>;
59 using _4 = SizedOp<Aarch64Backend, 4>;
60 using _8 = SizedOp<Aarch64Backend, 8>;
61 using _16 = SizedOp<Aarch64Backend, 16>;
62 using _32 = SizedOp<Aarch64Backend, 32>;
63 using _64 = SizedOp<Aarch64Backend, 64>;
64 using _128 = SizedOp<Aarch64Backend, 128>;
65 } // namespace aarch64
66
67 } // namespace __llvm_libc
68
69 #endif // LLVM_LIBC_ARCH_AARCH64
70
71 #endif // LLVM_LIBC_SRC_STRING_MEMORY_UTILS_BACKEND_AARCH64_H
72