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