Botan 3.8.1
Crypto and TLS for C&
Botan::SIMD_4x32 Class Referencefinal

#include <simd_4x32.h>

Public Member Functions

SIMD_4x32 andc (const SIMD_4x32 &other) const noexcept
 
BOTAN_FN_ISA_SIMD_4X32 SIMD_4x32 bswap () const noexcept
 
SIMD_4x32 operator& (const SIMD_4x32 &other) const noexcept
 
void operator&= (const SIMD_4x32 &other) noexcept
 
SIMD_4x32 operator+ (const SIMD_4x32 &other) const noexcept
 
void operator+= (const SIMD_4x32 &other) noexcept
 
SIMD_4x32 operator- (const SIMD_4x32 &other) const noexcept
 
void operator-= (const SIMD_4x32 &other) noexcept
 
SIMD_4x32operator= (const SIMD_4x32 &other)=default
 
SIMD_4x32operator= (SIMD_4x32 &&other)=default
 
SIMD_4x32 operator^ (const SIMD_4x32 &other) const noexcept
 
void operator^= (const SIMD_4x32 &other) noexcept
 
void operator^= (uint32_t other) noexcept
 
SIMD_4x32 operator| (const SIMD_4x32 &other) const noexcept
 
void operator|= (const SIMD_4x32 &other) noexcept
 
SIMD_4x32 operator~ () const noexcept
 
native_simd_type raw () const noexcept
 
template<size_t ROT>
requires (ROT > 0 && ROT < 32)
BOTAN_FN_ISA_SIMD_4X32 SIMD_4x32 rotl () const noexcept
 
template<size_t ROT>
SIMD_4x32 rotr () const noexcept
 
template<size_t I>
requires (I <= 3)
SIMD_4x32 shift_elems_left () const noexcept
 
template<size_t I>
requires (I <= 3)
SIMD_4x32 shift_elems_right () const noexcept
 
template<int SHIFT>
requires (SHIFT > 0 && SHIFT < 32)
SIMD_4x32 shl () const noexcept
 
template<int SHIFT>
SIMD_4x32 shr () const noexcept
 
SIMD_4x32 sigma0 () const noexcept
 
SIMD_4x32 sigma1 () const noexcept
 
 SIMD_4x32 () noexcept
 
 SIMD_4x32 (const SIMD_4x32 &other)=default
 
 SIMD_4x32 (native_simd_type x) noexcept
 
 SIMD_4x32 (SIMD_4x32 &&other)=default
 
 SIMD_4x32 (uint32_t B0, uint32_t B1, uint32_t B2, uint32_t B3) noexcept
 
void store_be (std::span< uint8_t, 16 > out) const
 
void store_be (uint32_t out[4]) const noexcept
 
BOTAN_FN_ISA_SIMD_4X32 void store_be (uint8_t out[]) const noexcept
 
void store_le (std::span< uint8_t, 16 > out) const
 
void store_le (uint32_t out[4]) const noexcept
 
void store_le (uint64_t out[2]) const noexcept
 
void store_le (uint8_t out[]) const noexcept
 
 ~SIMD_4x32 ()=default
 

Static Public Member Functions

static SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 alignr4 (const SIMD_4x32 &a, const SIMD_4x32 &b)
 
static SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 alignr8 (const SIMD_4x32 &a, const SIMD_4x32 &b)
 
static SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 byte_shuffle (const SIMD_4x32 &tbl, const SIMD_4x32 &idx)
 
static SIMD_4x32 choose (const SIMD_4x32 &mask, const SIMD_4x32 &a, const SIMD_4x32 &b) noexcept
 
static SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 load_be (const void *in) noexcept
 
static SIMD_4x32 load_be (std::span< const uint8_t, 16 > in)
 
static SIMD_4x32 load_le (const void *in) noexcept
 
static SIMD_4x32 load_le (std::span< const uint8_t, 16 > in)
 
static SIMD_4x32 majority (const SIMD_4x32 &x, const SIMD_4x32 &y, const SIMD_4x32 &z) noexcept
 
static SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 masked_byte_shuffle (const SIMD_4x32 &tbl, const SIMD_4x32 &idx)
 
static SIMD_4x32 splat (uint32_t B) noexcept
 
static SIMD_4x32 splat_u8 (uint8_t B) noexcept
 
static void transpose (SIMD_4x32 &B0, SIMD_4x32 &B1, SIMD_4x32 &B2, SIMD_4x32 &B3) noexcept
 

Detailed Description

4x32 bit SIMD register

This class is not a general purpose SIMD type, and only offers instructions needed for evaluation of specific crypto primitives. For example it does not currently have equality operators of any kind.

Implemented for SSE2, VMX (Altivec), ARMv7/Aarch64 NEON, and LoongArch LSX

Definition at line 64 of file simd_4x32.h.

Constructor & Destructor Documentation

◆ SIMD_4x32() [1/5]

◆ SIMD_4x32() [2/5]

Botan::SIMD_4x32::SIMD_4x32 ( SIMD_4x32 && other)
default

References SIMD_4x32().

◆ ~SIMD_4x32()

Botan::SIMD_4x32::~SIMD_4x32 ( )
default

◆ SIMD_4x32() [3/5]

Botan::SIMD_4x32::SIMD_4x32 ( )
inlinenoexcept

Zero initialize SIMD register with 4 32-bit elements

Definition at line 77 of file simd_4x32.h.

77 {
78#if defined(BOTAN_SIMD_USE_SSSE3)
79 m_simd = _mm_setzero_si128();
80#elif defined(BOTAN_SIMD_USE_ALTIVEC)
81 m_simd = vec_splat_u32(0);
82#elif defined(BOTAN_SIMD_USE_NEON)
83 m_simd = vdupq_n_u32(0);
84#elif defined(BOTAN_SIMD_USE_LSX)
85 m_simd = __lsx_vldi(0);
86#endif
87 }

Referenced by alignr4(), alignr8(), andc(), bswap(), byte_shuffle(), choose(), load_be(), load_le(), masked_byte_shuffle(), operator~(), rotl(), shift_elems_left(), shift_elems_right(), shl(), shr(), sigma0(), sigma1(), splat(), and splat_u8().

◆ SIMD_4x32() [4/5]

Botan::SIMD_4x32::SIMD_4x32 ( uint32_t B0,
uint32_t B1,
uint32_t B2,
uint32_t B3 )
inlinenoexcept

Load SIMD register with 4 32-bit elements

Definition at line 92 of file simd_4x32.h.

92 {
93#if defined(BOTAN_SIMD_USE_SSSE3)
94 m_simd = _mm_set_epi32(B3, B2, B1, B0);
95#elif defined(BOTAN_SIMD_USE_ALTIVEC)
96 __vector unsigned int val = {B0, B1, B2, B3};
97 m_simd = val;
98#elif defined(BOTAN_SIMD_USE_NEON)
99 // Better way to do this?
100 const uint32_t B[4] = {B0, B1, B2, B3};
101 m_simd = vld1q_u32(B);
102#elif defined(BOTAN_SIMD_USE_LSX)
103 // Better way to do this?
104 const uint32_t B[4] = {B0, B1, B2, B3};
105 m_simd = __lsx_vld(B, 0);
106#endif
107 }

◆ SIMD_4x32() [5/5]

Botan::SIMD_4x32::SIMD_4x32 ( native_simd_type x)
inlineexplicitnoexcept

Definition at line 756 of file simd_4x32.h.

756: m_simd(x) {}

Member Function Documentation

◆ alignr4()

static SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 Botan::SIMD_4x32::alignr4 ( const SIMD_4x32 & a,
const SIMD_4x32 & b )
inlinestatic

Definition at line 727 of file simd_4x32.h.

727 {
728#if defined(BOTAN_SIMD_USE_SSSE3)
729 return SIMD_4x32(_mm_alignr_epi8(a.raw(), b.raw(), 4));
730#elif defined(BOTAN_SIMD_USE_NEON)
731 return SIMD_4x32(vextq_u32(b.raw(), a.raw(), 1));
732#elif defined(BOTAN_SIMD_USE_ALTIVEC)
733 const __vector unsigned char mask = {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
734 return SIMD_4x32(vec_perm(b.raw(), a.raw(), mask));
735#elif defined(BOTAN_SIMD_USE_LSX)
736 const auto mask = SIMD_4x32(0x07060504, 0x0B0A0908, 0x0F0E0D0C, 0x13121110);
737 return SIMD_4x32(__lsx_vshuf_b(a.raw(), b.raw(), mask.raw()));
738#endif
739 }
SIMD_4x32() noexcept
Definition simd_4x32.h:77

References raw(), SIMD_4x32(), and SIMD_4x32().

◆ alignr8()

static SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 Botan::SIMD_4x32::alignr8 ( const SIMD_4x32 & a,
const SIMD_4x32 & b )
inlinestatic

Definition at line 741 of file simd_4x32.h.

741 {
742#if defined(BOTAN_SIMD_USE_SSSE3)
743 return SIMD_4x32(_mm_alignr_epi8(a.raw(), b.raw(), 8));
744#elif defined(BOTAN_SIMD_USE_NEON)
745 return SIMD_4x32(vextq_u32(b.raw(), a.raw(), 2));
746#elif defined(BOTAN_SIMD_USE_ALTIVEC)
747 const __vector unsigned char mask = {8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23};
748 return SIMD_4x32(vec_perm(b.raw(), a.raw(), mask));
749#elif defined(BOTAN_SIMD_USE_LSX)
750 return SIMD_4x32(__lsx_vshuf4i_d(a.raw(), b.raw(), 0b0011));
751#endif
752 }

References raw(), SIMD_4x32(), and SIMD_4x32().

◆ andc()

SIMD_4x32 Botan::SIMD_4x32::andc ( const SIMD_4x32 & other) const
inlinenoexcept

Definition at line 493 of file simd_4x32.h.

493 {
494#if defined(BOTAN_SIMD_USE_SSSE3)
495 return SIMD_4x32(_mm_andnot_si128(m_simd, other.m_simd));
496#elif defined(BOTAN_SIMD_USE_ALTIVEC)
497 /*
498 AltiVec does arg1 & ~arg2 rather than SSE's ~arg1 & arg2
499 so swap the arguments
500 */
501 return SIMD_4x32(vec_andc(other.m_simd, m_simd));
502#elif defined(BOTAN_SIMD_USE_NEON)
503 // NEON is also a & ~b
504 return SIMD_4x32(vbicq_u32(other.m_simd, m_simd));
505#elif defined(BOTAN_SIMD_USE_LSX)
506 // LSX is ~a & b
507 return SIMD_4x32(__lsx_vandn_v(m_simd, other.m_simd));
508#endif
509 }

References SIMD_4x32(), and SIMD_4x32().

◆ bswap()

BOTAN_FN_ISA_SIMD_4X32 SIMD_4x32 Botan::SIMD_4x32::bswap ( ) const
inlinenoexcept

Return copy *this with each word byte swapped

Definition at line 514 of file simd_4x32.h.

514 {
515#if defined(BOTAN_SIMD_USE_SSSE3)
516 const auto idx = _mm_set_epi8(12, 13, 14, 15, 8, 9, 10, 11, 4, 5, 6, 7, 0, 1, 2, 3);
517
518 return SIMD_4x32(_mm_shuffle_epi8(raw(), idx));
519#elif defined(BOTAN_SIMD_USE_ALTIVEC)
520 #ifdef BOTAN_SIMD_USE_VSX
521 return SIMD_4x32(vec_revb(m_simd));
522 #else
523 const __vector unsigned char rev[1] = {
524 {3, 2, 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12},
525 };
526
527 return SIMD_4x32(vec_perm(m_simd, m_simd, rev[0]));
528 #endif
529
530#elif defined(BOTAN_SIMD_USE_NEON)
531 return SIMD_4x32(vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(m_simd))));
532#elif defined(BOTAN_SIMD_USE_LSX)
533 return SIMD_4x32(__lsx_vshuf4i_b(m_simd, 0b00011011));
534#endif
535 }
native_simd_type raw() const noexcept
Definition simd_4x32.h:754

References raw(), SIMD_4x32(), and SIMD_4x32().

Referenced by load_be(), load_le(), store_be(), and store_le().

◆ byte_shuffle()

static SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 Botan::SIMD_4x32::byte_shuffle ( const SIMD_4x32 & tbl,
const SIMD_4x32 & idx )
inlinestatic

Byte shuffle

This function assumes that each byte of idx is <= 16; it may produce incorrect results if this does not hold.

Definition at line 663 of file simd_4x32.h.

663 {
664#if defined(BOTAN_SIMD_USE_SSSE3)
665 return SIMD_4x32(_mm_shuffle_epi8(tbl.raw(), idx.raw()));
666#elif defined(BOTAN_SIMD_USE_NEON)
667 const uint8x16_t tbl8 = vreinterpretq_u8_u32(tbl.raw());
668 const uint8x16_t idx8 = vreinterpretq_u8_u32(idx.raw());
669
670 #if defined(BOTAN_TARGET_ARCH_IS_ARM32)
671 const uint8x8x2_t tbl2 = {vget_low_u8(tbl8), vget_high_u8(tbl8)};
672
673 return SIMD_4x32(
674 vreinterpretq_u32_u8(vcombine_u8(vtbl2_u8(tbl2, vget_low_u8(idx8)), vtbl2_u8(tbl2, vget_high_u8(idx8)))));
675 #else
676 return SIMD_4x32(vreinterpretq_u32_u8(vqtbl1q_u8(tbl8, idx8)));
677 #endif
678
679#elif defined(BOTAN_SIMD_USE_ALTIVEC)
680 const auto r = vec_perm(reinterpret_cast<__vector signed char>(tbl.raw()),
681 reinterpret_cast<__vector signed char>(tbl.raw()),
682 reinterpret_cast<__vector unsigned char>(idx.raw()));
683 return SIMD_4x32(reinterpret_cast<__vector unsigned int>(r));
684#elif defined(BOTAN_SIMD_USE_LSX)
685 return SIMD_4x32(__lsx_vshuf_b(tbl.raw(), tbl.raw(), idx.raw()));
686#endif
687 }

References raw(), SIMD_4x32(), and SIMD_4x32().

Referenced by masked_byte_shuffle().

◆ choose()

static SIMD_4x32 Botan::SIMD_4x32::choose ( const SIMD_4x32 & mask,
const SIMD_4x32 & a,
const SIMD_4x32 & b )
inlinestaticnoexcept

Definition at line 641 of file simd_4x32.h.

641 {
642#if defined(BOTAN_SIMD_USE_ALTIVEC)
643 return SIMD_4x32(vec_sel(b.raw(), a.raw(), mask.raw()));
644#elif defined(BOTAN_SIMD_USE_NEON)
645 return SIMD_4x32(vbslq_u32(mask.raw(), a.raw(), b.raw()));
646#elif defined(BOTAN_SIMD_USE_LSX)
647 return SIMD_4x32(__lsx_vbitsel_v(b.raw(), a.raw(), mask.raw()));
648#else
649 return (mask & a) ^ mask.andc(b);
650#endif
651 }

References SIMD_4x32(), and SIMD_4x32().

Referenced by majority().

◆ load_be() [1/2]

static SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 Botan::SIMD_4x32::load_be ( const void * in)
inlinestaticnoexcept

Load a SIMD register with big-endian convention

Definition at line 166 of file simd_4x32.h.

166 {
167#if defined(BOTAN_SIMD_USE_SSSE3) || defined(BOTAN_SIMD_USE_LSX)
168 return load_le(in).bswap();
169
170#elif defined(BOTAN_SIMD_USE_ALTIVEC)
171 uint32_t R[4];
172 Botan::load_be(R, static_cast<const uint8_t*>(in), 4);
173 __vector unsigned int val = {R[0], R[1], R[2], R[3]};
174 return SIMD_4x32(val);
175
176#elif defined(BOTAN_SIMD_USE_NEON)
177 SIMD_4x32 l(vld1q_u32(static_cast<const uint32_t*>(in)));
178 if constexpr(std::endian::native == std::endian::little) {
179 return l.bswap();
180 } else {
181 return l;
182 }
183#endif
184 }
static SIMD_4x32 load_le(const void *in) noexcept
Definition simd_4x32.h:143
SIMD_4x32(const SIMD_4x32 &other)=default
BOTAN_FN_ISA_SIMD_4X32 SIMD_4x32 bswap() const noexcept
Definition simd_4x32.h:514
constexpr auto load_be(ParamTs &&... params)
Definition loadstor.h:504

References bswap(), Botan::load_be(), load_le(), SIMD_4x32(), and SIMD_4x32().

Referenced by Botan::SHA_256::compress_digest_x86(), load_be(), and Botan::SHA_1::sha1_compress_x86().

◆ load_be() [2/2]

static SIMD_4x32 Botan::SIMD_4x32::load_be ( std::span< const uint8_t, 16 > in)
inlinestatic

Definition at line 188 of file simd_4x32.h.

188{ return SIMD_4x32::load_be(in.data()); }
static SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 load_be(const void *in) noexcept
Definition simd_4x32.h:166

References load_be(), and SIMD_4x32().

◆ load_le() [1/2]

static SIMD_4x32 Botan::SIMD_4x32::load_le ( const void * in)
inlinestaticnoexcept

Load a SIMD register with little-endian convention

Definition at line 143 of file simd_4x32.h.

143 {
144#if defined(BOTAN_SIMD_USE_SSSE3)
145 return SIMD_4x32(_mm_loadu_si128(reinterpret_cast<const __m128i*>(in)));
146#elif defined(BOTAN_SIMD_USE_ALTIVEC)
147 uint32_t R[4];
148 Botan::load_le(R, static_cast<const uint8_t*>(in), 4);
149 __vector unsigned int val = {R[0], R[1], R[2], R[3]};
150 return SIMD_4x32(val);
151#elif defined(BOTAN_SIMD_USE_NEON)
152 SIMD_4x32 l(vld1q_u32(static_cast<const uint32_t*>(in)));
153 if constexpr(std::endian::native == std::endian::big) {
154 return l.bswap();
155 } else {
156 return l;
157 }
158#elif defined(BOTAN_SIMD_USE_LSX)
159 return SIMD_4x32(__lsx_vld(in, 0));
160#endif
161 }
constexpr auto load_le(ParamTs &&... params)
Definition loadstor.h:495

References bswap(), Botan::load_le(), SIMD_4x32(), and SIMD_4x32().

Referenced by Botan::SHA_256::compress_digest_x86(), load_be(), load_le(), and Botan::SHA_1::sha1_compress_x86().

◆ load_le() [2/2]

static SIMD_4x32 Botan::SIMD_4x32::load_le ( std::span< const uint8_t, 16 > in)
inlinestatic

Definition at line 186 of file simd_4x32.h.

186{ return SIMD_4x32::load_le(in.data()); }

References load_le(), and SIMD_4x32().

◆ majority()

static SIMD_4x32 Botan::SIMD_4x32::majority ( const SIMD_4x32 & x,
const SIMD_4x32 & y,
const SIMD_4x32 & z )
inlinestaticnoexcept

Definition at line 653 of file simd_4x32.h.

653 {
654 return SIMD_4x32::choose(x ^ y, z, y);
655 }
static SIMD_4x32 choose(const SIMD_4x32 &mask, const SIMD_4x32 &a, const SIMD_4x32 &b) noexcept
Definition simd_4x32.h:641

References choose(), and SIMD_4x32().

◆ masked_byte_shuffle()

static SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 Botan::SIMD_4x32::masked_byte_shuffle ( const SIMD_4x32 & tbl,
const SIMD_4x32 & idx )
inlinestatic

Byte shuffle with masking

If the index is >= 128 then the output byte is set to zero.

Warning: for indices between 16 and 128 this function may have different behaviors depending on the CPU; possibly the output is zero, tbl[idx % 16], or even undefined.

Definition at line 698 of file simd_4x32.h.

698 {
699#if defined(BOTAN_SIMD_USE_ALTIVEC)
700 const auto zero = vec_splat_s8(0x00);
701 const auto mask = vec_cmplt(reinterpret_cast<__vector signed char>(idx.raw()), zero);
702 const auto r = vec_perm(reinterpret_cast<__vector signed char>(tbl.raw()),
703 reinterpret_cast<__vector signed char>(tbl.raw()),
704 reinterpret_cast<__vector unsigned char>(idx.raw()));
705 return SIMD_4x32(reinterpret_cast<__vector unsigned int>(vec_sel(r, zero, mask)));
706#elif defined(BOTAN_SIMD_USE_LSX)
707 /*
708 * The behavior of vshuf.b unfortunately differs among microarchitectures
709 * when the index is larger than the available elements. In LA664 CPUs,
710 * larger indices result in a zero byte, which is exactly what we want.
711 * Unfortunately on LA464 machines, the output is instead undefined.
712 *
713 * So we must use a slower sequence that handles the larger indices.
714 * If we had a way of knowing at compile time that we are on an LA664
715 * or later, we could use __lsx_vshuf_b without the comparison or select.
716 */
717 const auto zero = __lsx_vldi(0);
718 const auto r = __lsx_vshuf_b(zero, tbl.raw(), idx.raw());
719 const auto mask = __lsx_vslti_bu(idx.raw(), 16);
720 return SIMD_4x32(__lsx_vbitsel_v(zero, r, mask));
721#else
722 // ARM and x86 byte shuffles have the behavior we want for out of range idx
723 return SIMD_4x32::byte_shuffle(tbl, idx);
724#endif
725 }
static SIMD_4x32 BOTAN_FN_ISA_SIMD_4X32 byte_shuffle(const SIMD_4x32 &tbl, const SIMD_4x32 &idx)
Definition simd_4x32.h:663

References byte_shuffle(), raw(), SIMD_4x32(), and SIMD_4x32().

◆ operator&()

SIMD_4x32 Botan::SIMD_4x32::operator& ( const SIMD_4x32 & other) const
inlinenoexcept

Binary AND elements of a SIMD vector

Definition at line 378 of file simd_4x32.h.

378 {
379 SIMD_4x32 retval(*this);
380 retval &= other;
381 return retval;
382 }

References SIMD_4x32().

◆ operator&=()

void Botan::SIMD_4x32::operator&= ( const SIMD_4x32 & other)
inlinenoexcept

Definition at line 434 of file simd_4x32.h.

434 {
435#if defined(BOTAN_SIMD_USE_SSSE3)
436 m_simd = _mm_and_si128(m_simd, other.m_simd);
437#elif defined(BOTAN_SIMD_USE_ALTIVEC)
438 m_simd = vec_and(m_simd, other.m_simd);
439#elif defined(BOTAN_SIMD_USE_NEON)
440 m_simd = vandq_u32(m_simd, other.m_simd);
441#elif defined(BOTAN_SIMD_USE_LSX)
442 m_simd = __lsx_vand_v(m_simd, other.m_simd);
443#endif
444 }

References SIMD_4x32().

◆ operator+()

SIMD_4x32 Botan::SIMD_4x32::operator+ ( const SIMD_4x32 & other) const
inlinenoexcept

Add elements of a SIMD vector

Definition at line 342 of file simd_4x32.h.

342 {
343 SIMD_4x32 retval(*this);
344 retval += other;
345 return retval;
346 }

References SIMD_4x32().

◆ operator+=()

void Botan::SIMD_4x32::operator+= ( const SIMD_4x32 & other)
inlinenoexcept

Definition at line 384 of file simd_4x32.h.

384 {
385#if defined(BOTAN_SIMD_USE_SSSE3)
386 m_simd = _mm_add_epi32(m_simd, other.m_simd);
387#elif defined(BOTAN_SIMD_USE_ALTIVEC)
388 m_simd = vec_add(m_simd, other.m_simd);
389#elif defined(BOTAN_SIMD_USE_NEON)
390 m_simd = vaddq_u32(m_simd, other.m_simd);
391#elif defined(BOTAN_SIMD_USE_LSX)
392 m_simd = __lsx_vadd_w(m_simd, other.m_simd);
393#endif
394 }

References SIMD_4x32().

◆ operator-()

SIMD_4x32 Botan::SIMD_4x32::operator- ( const SIMD_4x32 & other) const
inlinenoexcept

Subtract elements of a SIMD vector

Definition at line 351 of file simd_4x32.h.

351 {
352 SIMD_4x32 retval(*this);
353 retval -= other;
354 return retval;
355 }

References SIMD_4x32().

◆ operator-=()

void Botan::SIMD_4x32::operator-= ( const SIMD_4x32 & other)
inlinenoexcept

Definition at line 396 of file simd_4x32.h.

396 {
397#if defined(BOTAN_SIMD_USE_SSSE3)
398 m_simd = _mm_sub_epi32(m_simd, other.m_simd);
399#elif defined(BOTAN_SIMD_USE_ALTIVEC)
400 m_simd = vec_sub(m_simd, other.m_simd);
401#elif defined(BOTAN_SIMD_USE_NEON)
402 m_simd = vsubq_u32(m_simd, other.m_simd);
403#elif defined(BOTAN_SIMD_USE_LSX)
404 m_simd = __lsx_vsub_w(m_simd, other.m_simd);
405#endif
406 }

References SIMD_4x32().

◆ operator=() [1/2]

SIMD_4x32 & Botan::SIMD_4x32::operator= ( const SIMD_4x32 & other)
default

References SIMD_4x32().

◆ operator=() [2/2]

SIMD_4x32 & Botan::SIMD_4x32::operator= ( SIMD_4x32 && other)
default

References SIMD_4x32().

◆ operator^()

SIMD_4x32 Botan::SIMD_4x32::operator^ ( const SIMD_4x32 & other) const
inlinenoexcept

XOR elements of a SIMD vector

Definition at line 360 of file simd_4x32.h.

360 {
361 SIMD_4x32 retval(*this);
362 retval ^= other;
363 return retval;
364 }

References SIMD_4x32().

◆ operator^=() [1/2]

void Botan::SIMD_4x32::operator^= ( const SIMD_4x32 & other)
inlinenoexcept

Definition at line 408 of file simd_4x32.h.

408 {
409#if defined(BOTAN_SIMD_USE_SSSE3)
410 m_simd = _mm_xor_si128(m_simd, other.m_simd);
411#elif defined(BOTAN_SIMD_USE_ALTIVEC)
412 m_simd = vec_xor(m_simd, other.m_simd);
413#elif defined(BOTAN_SIMD_USE_NEON)
414 m_simd = veorq_u32(m_simd, other.m_simd);
415#elif defined(BOTAN_SIMD_USE_LSX)
416 m_simd = __lsx_vxor_v(m_simd, other.m_simd);
417#endif
418 }

References SIMD_4x32().

◆ operator^=() [2/2]

void Botan::SIMD_4x32::operator^= ( uint32_t other)
inlinenoexcept

Definition at line 420 of file simd_4x32.h.

420{ *this ^= SIMD_4x32::splat(other); }
static SIMD_4x32 splat(uint32_t B) noexcept
Definition simd_4x32.h:112

References splat().

◆ operator|()

SIMD_4x32 Botan::SIMD_4x32::operator| ( const SIMD_4x32 & other) const
inlinenoexcept

Binary OR elements of a SIMD vector

Definition at line 369 of file simd_4x32.h.

369 {
370 SIMD_4x32 retval(*this);
371 retval |= other;
372 return retval;
373 }

References SIMD_4x32().

◆ operator|=()

void Botan::SIMD_4x32::operator|= ( const SIMD_4x32 & other)
inlinenoexcept

Definition at line 422 of file simd_4x32.h.

422 {
423#if defined(BOTAN_SIMD_USE_SSSE3)
424 m_simd = _mm_or_si128(m_simd, other.m_simd);
425#elif defined(BOTAN_SIMD_USE_ALTIVEC)
426 m_simd = vec_or(m_simd, other.m_simd);
427#elif defined(BOTAN_SIMD_USE_NEON)
428 m_simd = vorrq_u32(m_simd, other.m_simd);
429#elif defined(BOTAN_SIMD_USE_LSX)
430 m_simd = __lsx_vor_v(m_simd, other.m_simd);
431#endif
432 }

References SIMD_4x32().

◆ operator~()

SIMD_4x32 Botan::SIMD_4x32::operator~ ( ) const
inlinenoexcept

Definition at line 480 of file simd_4x32.h.

480 {
481#if defined(BOTAN_SIMD_USE_SSSE3)
482 return SIMD_4x32(_mm_xor_si128(m_simd, _mm_set1_epi32(0xFFFFFFFF)));
483#elif defined(BOTAN_SIMD_USE_ALTIVEC)
484 return SIMD_4x32(vec_nor(m_simd, m_simd));
485#elif defined(BOTAN_SIMD_USE_NEON)
486 return SIMD_4x32(vmvnq_u32(m_simd));
487#elif defined(BOTAN_SIMD_USE_LSX)
488 return SIMD_4x32(__lsx_vnor_v(m_simd, m_simd));
489#endif
490 }

References SIMD_4x32(), and SIMD_4x32().

◆ raw()

native_simd_type Botan::SIMD_4x32::raw ( ) const
inlinenoexcept

◆ rotl()

template<size_t ROT>
requires (ROT > 0 && ROT < 32)
BOTAN_FN_ISA_SIMD_4X32 SIMD_4x32 Botan::SIMD_4x32::rotl ( ) const
inlinenoexcept

Left rotation by a compile time constant

Definition at line 288 of file simd_4x32.h.

290 {
291#if defined(BOTAN_SIMD_USE_SSSE3)
292 if constexpr(ROT == 8) {
293 const auto shuf_rotl_8 = _mm_set_epi64x(0x0e0d0c0f0a09080b, 0x0605040702010003);
294 return SIMD_4x32(_mm_shuffle_epi8(raw(), shuf_rotl_8));
295 } else if constexpr(ROT == 16) {
296 const auto shuf_rotl_16 = _mm_set_epi64x(0x0d0c0f0e09080b0a, 0x0504070601000302);
297 return SIMD_4x32(_mm_shuffle_epi8(raw(), shuf_rotl_16));
298 } else if constexpr(ROT == 24) {
299 const auto shuf_rotl_24 = _mm_set_epi64x(0x0c0f0e0d080b0a09, 0x0407060500030201);
300 return SIMD_4x32(_mm_shuffle_epi8(raw(), shuf_rotl_24));
301 } else {
302 return SIMD_4x32(_mm_or_si128(_mm_slli_epi32(raw(), static_cast<int>(ROT)),
303 _mm_srli_epi32(raw(), static_cast<int>(32 - ROT))));
304 }
305
306#elif defined(BOTAN_SIMD_USE_ALTIVEC)
307
308 const unsigned int r = static_cast<unsigned int>(ROT);
309 __vector unsigned int rot = {r, r, r, r};
310 return SIMD_4x32(vec_rl(m_simd, rot));
311
312#elif defined(BOTAN_SIMD_USE_NEON)
313
314 #if defined(BOTAN_TARGET_ARCH_IS_ARM64)
315
316 if constexpr(ROT == 8) {
317 const uint8_t maskb[16] = {3, 0, 1, 2, 7, 4, 5, 6, 11, 8, 9, 10, 15, 12, 13, 14};
318 const uint8x16_t mask = vld1q_u8(maskb);
319 return SIMD_4x32(vreinterpretq_u32_u8(vqtbl1q_u8(vreinterpretq_u8_u32(m_simd), mask)));
320 } else if constexpr(ROT == 16) {
321 return SIMD_4x32(vreinterpretq_u32_u16(vrev32q_u16(vreinterpretq_u16_u32(m_simd))));
322 }
323 #endif
324 return SIMD_4x32(
325 vorrq_u32(vshlq_n_u32(m_simd, static_cast<int>(ROT)), vshrq_n_u32(m_simd, static_cast<int>(32 - ROT))));
326#elif defined(BOTAN_SIMD_USE_LSX)
327 return SIMD_4x32(__lsx_vrotri_w(raw(), 32 - ROT));
328#endif
329 }

References raw(), SIMD_4x32(), and SIMD_4x32().

Referenced by Botan::rotl(), and rotr().

◆ rotr()

template<size_t ROT>
SIMD_4x32 Botan::SIMD_4x32::rotr ( ) const
inlinenoexcept

Right rotation by a compile time constant

Definition at line 335 of file simd_4x32.h.

335 {
336 return this->rotl<32 - ROT>();
337 }
BOTAN_FN_ISA_SIMD_4X32 SIMD_4x32 rotl() const noexcept
Definition simd_4x32.h:288

References rotl(), and SIMD_4x32().

Referenced by Botan::rotr(), sigma0(), and sigma1().

◆ shift_elems_left()

template<size_t I>
requires (I <= 3)
SIMD_4x32 Botan::SIMD_4x32::shift_elems_left ( ) const
inlinenoexcept

Definition at line 538 of file simd_4x32.h.

540 {
541#if defined(BOTAN_SIMD_USE_SSSE3)
542 return SIMD_4x32(_mm_slli_si128(raw(), 4 * I));
543#elif defined(BOTAN_SIMD_USE_NEON)
544 return SIMD_4x32(vextq_u32(vdupq_n_u32(0), raw(), 4 - I));
545#elif defined(BOTAN_SIMD_USE_ALTIVEC)
546 const __vector unsigned int zero = vec_splat_u32(0);
547
548 const __vector unsigned char shuf[3] = {
549 {16, 17, 18, 19, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11},
550 {16, 17, 18, 19, 20, 21, 22, 23, 0, 1, 2, 3, 4, 5, 6, 7},
551 {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 0, 1, 2, 3},
552 };
553
554 return SIMD_4x32(vec_perm(raw(), zero, shuf[I - 1]));
555#elif defined(BOTAN_SIMD_USE_LSX)
556 return SIMD_4x32(__lsx_vbsll_v(raw(), 4 * I));
557#endif
558 }

References raw(), SIMD_4x32(), and SIMD_4x32().

◆ shift_elems_right()

template<size_t I>
requires (I <= 3)
SIMD_4x32 Botan::SIMD_4x32::shift_elems_right ( ) const
inlinenoexcept

Definition at line 561 of file simd_4x32.h.

563 {
564#if defined(BOTAN_SIMD_USE_SSSE3)
565 return SIMD_4x32(_mm_srli_si128(raw(), 4 * I));
566#elif defined(BOTAN_SIMD_USE_NEON)
567 return SIMD_4x32(vextq_u32(raw(), vdupq_n_u32(0), I));
568#elif defined(BOTAN_SIMD_USE_ALTIVEC)
569 const __vector unsigned int zero = vec_splat_u32(0);
570
571 const __vector unsigned char shuf[3] = {
572 {4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19},
573 {8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23},
574 {12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27},
575 };
576
577 return SIMD_4x32(vec_perm(raw(), zero, shuf[I - 1]));
578#elif defined(BOTAN_SIMD_USE_LSX)
579 return SIMD_4x32(__lsx_vbsrl_v(raw(), 4 * I));
580#endif
581 }

References raw(), SIMD_4x32(), and SIMD_4x32().

◆ shl()

template<int SHIFT>
requires (SHIFT > 0 && SHIFT < 32)
SIMD_4x32 Botan::SIMD_4x32::shl ( ) const
inlinenoexcept

Definition at line 447 of file simd_4x32.h.

449 {
450#if defined(BOTAN_SIMD_USE_SSSE3)
451 return SIMD_4x32(_mm_slli_epi32(m_simd, SHIFT));
452
453#elif defined(BOTAN_SIMD_USE_ALTIVEC)
454 const unsigned int s = static_cast<unsigned int>(SHIFT);
455 const __vector unsigned int shifts = {s, s, s, s};
456 return SIMD_4x32(vec_sl(m_simd, shifts));
457#elif defined(BOTAN_SIMD_USE_NEON)
458 return SIMD_4x32(vshlq_n_u32(m_simd, SHIFT));
459#elif defined(BOTAN_SIMD_USE_LSX)
460 return SIMD_4x32(__lsx_vslli_w(m_simd, SHIFT));
461#endif
462 }

References SIMD_4x32(), and SIMD_4x32().

Referenced by Botan::shl().

◆ shr()

template<int SHIFT>
SIMD_4x32 Botan::SIMD_4x32::shr ( ) const
inlinenoexcept

Definition at line 465 of file simd_4x32.h.

465 {
466#if defined(BOTAN_SIMD_USE_SSSE3)
467 return SIMD_4x32(_mm_srli_epi32(m_simd, SHIFT));
468
469#elif defined(BOTAN_SIMD_USE_ALTIVEC)
470 const unsigned int s = static_cast<unsigned int>(SHIFT);
471 const __vector unsigned int shifts = {s, s, s, s};
472 return SIMD_4x32(vec_sr(m_simd, shifts));
473#elif defined(BOTAN_SIMD_USE_NEON)
474 return SIMD_4x32(vshrq_n_u32(m_simd, SHIFT));
475#elif defined(BOTAN_SIMD_USE_LSX)
476 return SIMD_4x32(__lsx_vsrli_w(m_simd, SHIFT));
477#endif
478 }

References SIMD_4x32(), and SIMD_4x32().

◆ sigma0()

SIMD_4x32 Botan::SIMD_4x32::sigma0 ( ) const
inlinenoexcept

Definition at line 259 of file simd_4x32.h.

259 {
260#if BOTAN_COMPILER_HAS_BUILTIN(__builtin_crypto_vshasigmaw) && defined(_ARCH_PWR8)
261 return SIMD_4x32(__builtin_crypto_vshasigmaw(raw(), 1, 0));
262#else
263 const SIMD_4x32 rot1 = this->rotr<2>();
264 const SIMD_4x32 rot2 = this->rotr<13>();
265 const SIMD_4x32 rot3 = this->rotr<22>();
266 return (rot1 ^ rot2 ^ rot3);
267#endif
268 }
SIMD_4x32 rotr() const noexcept
Definition simd_4x32.h:335

References raw(), rotr(), SIMD_4x32(), and SIMD_4x32().

◆ sigma1()

SIMD_4x32 Botan::SIMD_4x32::sigma1 ( ) const
inlinenoexcept

Definition at line 273 of file simd_4x32.h.

273 {
274#if BOTAN_COMPILER_HAS_BUILTIN(__builtin_crypto_vshasigmaw) && defined(_ARCH_PWR8)
275 return SIMD_4x32(__builtin_crypto_vshasigmaw(raw(), 1, 0xF));
276#else
277 const SIMD_4x32 rot1 = this->rotr<6>();
278 const SIMD_4x32 rot2 = this->rotr<11>();
279 const SIMD_4x32 rot3 = this->rotr<25>();
280 return (rot1 ^ rot2 ^ rot3);
281#endif
282 }

References raw(), rotr(), SIMD_4x32(), and SIMD_4x32().

◆ splat()

static SIMD_4x32 Botan::SIMD_4x32::splat ( uint32_t B)
inlinestaticnoexcept

Load SIMD register with one 32-bit element repeated

Definition at line 112 of file simd_4x32.h.

112 {
113#if defined(BOTAN_SIMD_USE_SSSE3)
114 return SIMD_4x32(_mm_set1_epi32(B));
115#elif defined(BOTAN_SIMD_USE_NEON)
116 return SIMD_4x32(vdupq_n_u32(B));
117#elif defined(BOTAN_SIMD_USE_LSX)
118 return SIMD_4x32(__lsx_vreplgr2vr_w(B));
119#else
120 return SIMD_4x32(B, B, B, B);
121#endif
122 }

References SIMD_4x32(), and SIMD_4x32().

Referenced by operator^=().

◆ splat_u8()

static SIMD_4x32 Botan::SIMD_4x32::splat_u8 ( uint8_t B)
inlinestaticnoexcept

Load SIMD register with one 8-bit element repeated

Definition at line 127 of file simd_4x32.h.

127 {
128#if defined(BOTAN_SIMD_USE_SSSE3)
129 return SIMD_4x32(_mm_set1_epi8(B));
130#elif defined(BOTAN_SIMD_USE_NEON)
131 return SIMD_4x32(vreinterpretq_u32_u8(vdupq_n_u8(B)));
132#elif defined(BOTAN_SIMD_USE_LSX)
133 return SIMD_4x32(__lsx_vreplgr2vr_b(B));
134#else
135 const uint32_t B4 = make_uint32(B, B, B, B);
136 return SIMD_4x32(B4, B4, B4, B4);
137#endif
138 }
constexpr uint32_t make_uint32(uint8_t i0, uint8_t i1, uint8_t i2, uint8_t i3)
Definition loadstor.h:104

References Botan::make_uint32(), SIMD_4x32(), and SIMD_4x32().

◆ store_be() [1/3]

void Botan::SIMD_4x32::store_be ( std::span< uint8_t, 16 > out) const
inline

Definition at line 252 of file simd_4x32.h.

252{ this->store_be(out.data()); }
void store_be(uint32_t out[4]) const noexcept
Definition simd_4x32.h:192

References store_be().

Referenced by store_be().

◆ store_be() [2/3]

void Botan::SIMD_4x32::store_be ( uint32_t out[4]) const
inlinenoexcept

Definition at line 192 of file simd_4x32.h.

192{ this->store_be(reinterpret_cast<uint8_t*>(out)); }

References store_be().

Referenced by store_be().

◆ store_be() [3/3]

BOTAN_FN_ISA_SIMD_4X32 void Botan::SIMD_4x32::store_be ( uint8_t out[]) const
inlinenoexcept

Load a SIMD register with big-endian convention

Definition at line 228 of file simd_4x32.h.

228 {
229#if defined(BOTAN_SIMD_USE_SSSE3) || defined(BOTAN_SIMD_USE_LSX)
230
231 bswap().store_le(out);
232
233#elif defined(BOTAN_SIMD_USE_ALTIVEC)
234
235 union {
236 __vector unsigned int V;
237 uint32_t R[4];
238 } vec;
239
240 vec.V = m_simd;
241 Botan::store_be(out, vec.R[0], vec.R[1], vec.R[2], vec.R[3]);
242
243#elif defined(BOTAN_SIMD_USE_NEON)
244 if constexpr(std::endian::native == std::endian::little) {
245 vst1q_u8(out, vreinterpretq_u8_u32(bswap().m_simd));
246 } else {
247 vst1q_u8(out, vreinterpretq_u8_u32(m_simd));
248 }
249#endif
250 }
void store_le(uint32_t out[4]) const noexcept
Definition simd_4x32.h:190
constexpr auto store_be(ParamTs &&... params)
Definition loadstor.h:745

References bswap(), Botan::store_be(), and store_le().

◆ store_le() [1/4]

void Botan::SIMD_4x32::store_le ( std::span< uint8_t, 16 > out) const
inline

Definition at line 254 of file simd_4x32.h.

254{ this->store_le(out.data()); }

References store_le().

Referenced by store_le().

◆ store_le() [2/4]

void Botan::SIMD_4x32::store_le ( uint32_t out[4]) const
inlinenoexcept

Definition at line 190 of file simd_4x32.h.

190{ this->store_le(reinterpret_cast<uint8_t*>(out)); }

References store_le().

Referenced by Botan::SHA_256::compress_digest_x86(), store_be(), and store_le().

◆ store_le() [3/4]

void Botan::SIMD_4x32::store_le ( uint64_t out[2]) const
inlinenoexcept

Definition at line 194 of file simd_4x32.h.

194{ this->store_le(reinterpret_cast<uint8_t*>(out)); }

References store_le().

Referenced by store_le().

◆ store_le() [4/4]

void Botan::SIMD_4x32::store_le ( uint8_t out[]) const
inlinenoexcept

Load a SIMD register with little-endian convention

Definition at line 199 of file simd_4x32.h.

199 {
200#if defined(BOTAN_SIMD_USE_SSSE3)
201
202 _mm_storeu_si128(reinterpret_cast<__m128i*>(out), raw());
203
204#elif defined(BOTAN_SIMD_USE_ALTIVEC)
205
206 union {
207 __vector unsigned int V;
208 uint32_t R[4];
209 } vec;
210
211 vec.V = raw();
212 Botan::store_le(out, vec.R[0], vec.R[1], vec.R[2], vec.R[3]);
213
214#elif defined(BOTAN_SIMD_USE_NEON)
215 if constexpr(std::endian::native == std::endian::little) {
216 vst1q_u8(out, vreinterpretq_u8_u32(m_simd));
217 } else {
218 vst1q_u8(out, vreinterpretq_u8_u32(bswap().m_simd));
219 }
220#elif defined(BOTAN_SIMD_USE_LSX)
221 __lsx_vst(raw(), out, 0);
222#endif
223 }
constexpr auto store_le(ParamTs &&... params)
Definition loadstor.h:736

References bswap(), raw(), and Botan::store_le().

◆ transpose()

static void Botan::SIMD_4x32::transpose ( SIMD_4x32 & B0,
SIMD_4x32 & B1,
SIMD_4x32 & B2,
SIMD_4x32 & B3 )
inlinestaticnoexcept

4x4 Transposition on SIMD registers

Definition at line 586 of file simd_4x32.h.

586 {
587#if defined(BOTAN_SIMD_USE_SSSE3)
588 const __m128i T0 = _mm_unpacklo_epi32(B0.m_simd, B1.m_simd);
589 const __m128i T1 = _mm_unpacklo_epi32(B2.m_simd, B3.m_simd);
590 const __m128i T2 = _mm_unpackhi_epi32(B0.m_simd, B1.m_simd);
591 const __m128i T3 = _mm_unpackhi_epi32(B2.m_simd, B3.m_simd);
592
593 B0.m_simd = _mm_unpacklo_epi64(T0, T1);
594 B1.m_simd = _mm_unpackhi_epi64(T0, T1);
595 B2.m_simd = _mm_unpacklo_epi64(T2, T3);
596 B3.m_simd = _mm_unpackhi_epi64(T2, T3);
597#elif defined(BOTAN_SIMD_USE_ALTIVEC)
598 const __vector unsigned int T0 = vec_mergeh(B0.m_simd, B2.m_simd);
599 const __vector unsigned int T1 = vec_mergeh(B1.m_simd, B3.m_simd);
600 const __vector unsigned int T2 = vec_mergel(B0.m_simd, B2.m_simd);
601 const __vector unsigned int T3 = vec_mergel(B1.m_simd, B3.m_simd);
602
603 B0.m_simd = vec_mergeh(T0, T1);
604 B1.m_simd = vec_mergel(T0, T1);
605 B2.m_simd = vec_mergeh(T2, T3);
606 B3.m_simd = vec_mergel(T2, T3);
607
608#elif defined(BOTAN_SIMD_USE_NEON) && defined(BOTAN_TARGET_ARCH_IS_ARM32)
609 const uint32x4x2_t T0 = vzipq_u32(B0.m_simd, B2.m_simd);
610 const uint32x4x2_t T1 = vzipq_u32(B1.m_simd, B3.m_simd);
611 const uint32x4x2_t O0 = vzipq_u32(T0.val[0], T1.val[0]);
612 const uint32x4x2_t O1 = vzipq_u32(T0.val[1], T1.val[1]);
613
614 B0.m_simd = O0.val[0];
615 B1.m_simd = O0.val[1];
616 B2.m_simd = O1.val[0];
617 B3.m_simd = O1.val[1];
618
619#elif defined(BOTAN_SIMD_USE_NEON) && defined(BOTAN_TARGET_ARCH_IS_ARM64)
620 const uint32x4_t T0 = vzip1q_u32(B0.m_simd, B2.m_simd);
621 const uint32x4_t T2 = vzip2q_u32(B0.m_simd, B2.m_simd);
622 const uint32x4_t T1 = vzip1q_u32(B1.m_simd, B3.m_simd);
623 const uint32x4_t T3 = vzip2q_u32(B1.m_simd, B3.m_simd);
624
625 B0.m_simd = vzip1q_u32(T0, T1);
626 B1.m_simd = vzip2q_u32(T0, T1);
627 B2.m_simd = vzip1q_u32(T2, T3);
628 B3.m_simd = vzip2q_u32(T2, T3);
629#elif defined(BOTAN_SIMD_USE_LSX)
630 const __m128i T0 = __lsx_vilvl_w(B2.raw(), B0.raw());
631 const __m128i T1 = __lsx_vilvh_w(B2.raw(), B0.raw());
632 const __m128i T2 = __lsx_vilvl_w(B3.raw(), B1.raw());
633 const __m128i T3 = __lsx_vilvh_w(B3.raw(), B1.raw());
634 B0.m_simd = __lsx_vilvl_w(T2, T0);
635 B1.m_simd = __lsx_vilvh_w(T2, T0);
636 B2.m_simd = __lsx_vilvl_w(T3, T1);
637 B3.m_simd = __lsx_vilvh_w(T3, T1);
638#endif
639 }

References SIMD_4x32().


The documentation for this class was generated from the following file: