3#include "native/isa_import.h"
4#include "native/arm/detail/crypto_constant.h"
5#include "native/arm/pmull.h"
6#include "native/targets.h"
10#if NATIVE_HOST_NEON || defined(NATIVE_DOXYGEN)
11namespace native::detail {
12 template<isa<arm> Arch>
13 constexpr simd<std::uint64_t,2,Arch> pmull_constant(std::uint64_t a,std::uint64_t b)
noexcept {
14 std::uint64_t low=0,high=0;
15 for(
unsigned bit=0;bit<64;++bit)
if((b>>bit)&1) {
17 if(bit) high^=a>>(64-bit);
19 return simd<std::uint64_t,2,Arch>(low,high);
37 template<isa<arm> Arch=NATIVE_BA
SELINE>
requires(Arch.has(arm_feature::pmull))
40 if consteval {
return detail::pmull_constant<Arch>(a,b); }
42 auto result = detail::arm_pmull::pmull<Arch>(a, b);
44 static_cast<std::uint64_t
>(result),
static_cast<std::uint64_t
>(result >> 64)})));
49 template<isa<arm> Arch=NATIVE_BA
SELINE>
50 requires(!Arch.has(arm_feature::pmull) &&
requires {
sizeof(simd<std::uint64_t,2,Arch>); })
52 return detail::pmull_constant<Arch>(a,b);
56 template<isa<arm> Arch>
requires(Arch.has(arm_feature::pmull))
59 if consteval {
return detail::pmull_constant<Arch>(detail::arm_constant::lanes(a)[1], detail::arm_constant::lanes(b)[1]); }
61 auto result = detail::arm_pmull::pmull2<Arch>(__builtin_bit_cast(poly64x2_t, a.to_native()), __builtin_bit_cast(poly64x2_t, b.to_native()));
63 static_cast<std::uint64_t
>(result),
static_cast<std::uint64_t
>(result >> 64)})));
68 template<isa<arm> Arch>
requires(!Arch.has(arm_feature::pmull) &&
requires {
sizeof(simd<std::uint64_t, 2, Arch>); })
70 return detail::pmull_constant<Arch>(detail::arm_constant::lanes(a)[1], detail::arm_constant::lanes(b)[1]);
74 template<isa<arm> Arch>
requires(Arch.has(arm_feature::neon))
77 if consteval {
return detail::arm_constant::pmull_bytes<simd<std::uint16_t, 8, Arch>, 0>(a, b); }
79 auto result = detail::arm_pmull::pmull<Arch>(vreinterpret_p8_u8(a.to_native()), vreinterpret_p8_u8(b.to_native()));
85 template<isa<arm> Arch>
requires(Arch.has(arm_feature::neon))
88 if consteval {
return detail::arm_constant::pmull_bytes<simd<std::uint16_t, 8, Arch>, 8>(a, b); }
90 auto result = detail::arm_pmull::pmull2<Arch>(vreinterpretq_p8_u8(a.to_native()), vreinterpretq_p8_u8(b.to_native()));
97 template<isa<arm> Arch=NATIVE_BA
SELINE,
class... T>
void pmull(T...) =
delete;
100 template<isa<arm> Arch,
class... T>
void pmull2(T...) =
delete;
constexpr simd< std::uint64_t, 2, Arch > pmull(std::uint64_t a, std::uint64_t b) noexcept
constexpr simd< std::uint64_t, 2, Arch > pmull2(simd< std::uint64_t, 2, Arch > a, simd< std::uint64_t, 2, Arch > b) noexcept
Multiply the high 64-bit polynomial lane of each operand; lower lanes are ignored.
#define native_inline
inline [[always_inline]]
#define native_nodiscard
C++17 [[nodiscard]].
#define native_const
[[const]] is not const
#define native_target(x)
this indicates a required feature set for the current multiversioned function.
Architecture-tagged vectors, register packs and supporting value types. Native arithmetic follows its...
Standard-library adaptations documented here for SIMD value types.
Omitted architecture arguments use the native.simd provider's baseline.