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> 26 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> 36 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 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