1 | //===-- RISC-V implementation of memory function building blocks ----------===// |
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 | // This file provides x86 specific building blocks to compose memory functions. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | #ifndef LLVM_LIBC_SRC_STRING_MEMORY_UTILS_OP_RISCV_H |
13 | #define LLVM_LIBC_SRC_STRING_MEMORY_UTILS_OP_RISCV_H |
14 | |
15 | #include "src/__support/macros/properties/architectures.h" |
16 | |
17 | #if defined(LIBC_TARGET_ARCH_IS_ANY_RISCV) |
18 | |
19 | #include "src/__support/common.h" |
20 | #include "src/string/memory_utils/op_generic.h" |
21 | |
22 | namespace LIBC_NAMESPACE::generic { |
23 | |
24 | /////////////////////////////////////////////////////////////////////////////// |
25 | // Specializations for uint16_t |
26 | template <> struct cmp_is_expensive<uint16_t> : public cpp::false_type {}; |
27 | template <> LIBC_INLINE bool eq<uint16_t>(CPtr p1, CPtr p2, size_t offset) { |
28 | return load<uint16_t>(p1, offset) == load<uint16_t>(p2, offset); |
29 | } |
30 | template <> |
31 | LIBC_INLINE uint32_t neq<uint16_t>(CPtr p1, CPtr p2, size_t offset) { |
32 | return load<uint16_t>(p1, offset) ^ load<uint16_t>(p2, offset); |
33 | } |
34 | template <> |
35 | LIBC_INLINE MemcmpReturnType cmp<uint16_t>(CPtr p1, CPtr p2, size_t offset) { |
36 | return static_cast<int32_t>(load_be<uint16_t>(p1, offset)) - |
37 | static_cast<int32_t>(load_be<uint16_t>(p2, offset)); |
38 | } |
39 | template <> |
40 | LIBC_INLINE MemcmpReturnType cmp_neq<uint16_t>(CPtr p1, CPtr p2, size_t offset); |
41 | |
42 | /////////////////////////////////////////////////////////////////////////////// |
43 | // Specializations for uint32_t |
44 | template <> struct cmp_is_expensive<uint32_t> : public cpp::false_type {}; |
45 | template <> LIBC_INLINE bool eq<uint32_t>(CPtr p1, CPtr p2, size_t offset) { |
46 | return load<uint32_t>(p1, offset) == load<uint32_t>(p2, offset); |
47 | } |
48 | template <> |
49 | LIBC_INLINE uint32_t neq<uint32_t>(CPtr p1, CPtr p2, size_t offset) { |
50 | return load<uint32_t>(p1, offset) ^ load<uint32_t>(p2, offset); |
51 | } |
52 | template <> |
53 | LIBC_INLINE MemcmpReturnType cmp<uint32_t>(CPtr p1, CPtr p2, size_t offset) { |
54 | const auto a = load_be<uint32_t>(p1, offset); |
55 | const auto b = load_be<uint32_t>(p2, offset); |
56 | return cmp_uint32_t(a, b); |
57 | } |
58 | template <> |
59 | LIBC_INLINE MemcmpReturnType cmp_neq<uint32_t>(CPtr p1, CPtr p2, size_t offset); |
60 | |
61 | /////////////////////////////////////////////////////////////////////////////// |
62 | // Specializations for uint64_t |
63 | template <> struct cmp_is_expensive<uint64_t> : public cpp::true_type {}; |
64 | template <> LIBC_INLINE bool eq<uint64_t>(CPtr p1, CPtr p2, size_t offset) { |
65 | return load<uint64_t>(p1, offset) == load<uint64_t>(p2, offset); |
66 | } |
67 | template <> |
68 | LIBC_INLINE uint32_t neq<uint64_t>(CPtr p1, CPtr p2, size_t offset) { |
69 | return !eq<uint64_t>(p1, p2, offset); |
70 | } |
71 | template <> |
72 | LIBC_INLINE MemcmpReturnType cmp<uint64_t>(CPtr p1, CPtr p2, size_t offset); |
73 | template <> |
74 | LIBC_INLINE MemcmpReturnType cmp_neq<uint64_t>(CPtr p1, CPtr p2, |
75 | size_t offset) { |
76 | const auto a = load_be<uint64_t>(p1, offset); |
77 | const auto b = load_be<uint64_t>(p2, offset); |
78 | return cmp_neq_uint64_t(a, b); |
79 | } |
80 | |
81 | } // namespace LIBC_NAMESPACE::generic |
82 | |
83 | #endif // LIBC_TARGET_ARCH_IS_ANY_RISCV |
84 | #endif // LLVM_LIBC_SRC_STRING_MEMORY_UTILS_OP_RISCV_H |
85 | |