blob: 3985b757d544046a13da289e852aec5ca76b4fe6 [file] [log] [blame]
/* SPDX-License-Identifier: Apache-2.0
* Copyright(c) 2021 Cisco Systems, Inc.
*/
#ifndef included_vector_index_to_ptr_h
#define included_vector_index_to_ptr_h
#include <vppinfra/clib.h>
#ifdef CLIB_HAVE_VEC128
static_always_inline void
clib_index_to_ptr_u32x4 (u32 *indices, void **ptrs, i32 i, u64x2 ov, u8 shift)
{
u32x4 iv4 = u32x4_load_unaligned (indices + i);
u64x2 pv2;
pv2 = u64x2_from_u32x4 (iv4);
u64x2_store_unaligned ((pv2 << shift) + ov, ptrs + i);
#ifdef __aarch64__
pv2 = u64x2_from_u32x4_high (iv4);
#else
pv2 = u64x2_from_u32x4 ((u32x4) u8x16_word_shift_right (iv4, 8));
#endif
u64x2_store_unaligned ((pv2 << shift) + ov, ptrs + i + 2);
}
#endif
/** \brief Convert array of indices to pointers with base and shift
@param indices source array of u32 indices
@param base base pointer
@param shift numbers of bits to be shifted
@param ptrs destinatin array of pointers
@param n_elts number of elements in the source array
*/
static_always_inline void
clib_index_to_ptr_u32 (u32 *indices, void *base, u8 shift, void **ptrs,
u32 n_elts)
{
#if defined CLIB_HAVE_VEC512
if (n_elts >= 8)
{
u64x8 off = u64x8_splat ((u64) base);
u64x8 b0, b1, b2, b3, b4, b5, b6, b7;
while (n_elts >= 64)
{
b0 = u64x8_from_u32x8 (u32x8_load_unaligned (indices));
b1 = u64x8_from_u32x8 (u32x8_load_unaligned (indices + 8));
b2 = u64x8_from_u32x8 (u32x8_load_unaligned (indices + 16));
b3 = u64x8_from_u32x8 (u32x8_load_unaligned (indices + 24));
b4 = u64x8_from_u32x8 (u32x8_load_unaligned (indices + 32));
b5 = u64x8_from_u32x8 (u32x8_load_unaligned (indices + 40));
b6 = u64x8_from_u32x8 (u32x8_load_unaligned (indices + 48));
b7 = u64x8_from_u32x8 (u32x8_load_unaligned (indices + 56));
u64x8_store_unaligned ((b0 << shift) + off, ptrs);
u64x8_store_unaligned ((b1 << shift) + off, ptrs + 8);
u64x8_store_unaligned ((b2 << shift) + off, ptrs + 16);
u64x8_store_unaligned ((b3 << shift) + off, ptrs + 24);
u64x8_store_unaligned ((b4 << shift) + off, ptrs + 32);
u64x8_store_unaligned ((b5 << shift) + off, ptrs + 40);
u64x8_store_unaligned ((b6 << shift) + off, ptrs + 48);
u64x8_store_unaligned ((b7 << shift) + off, ptrs + 56);
ptrs += 64;
indices += 64;
n_elts -= 64;
}
if (n_elts == 0)
return;
if (n_elts >= 32)
{
b0 = u64x8_from_u32x8 (u32x8_load_unaligned (indices));
b1 = u64x8_from_u32x8 (u32x8_load_unaligned (indices + 8));
b2 = u64x8_from_u32x8 (u32x8_load_unaligned (indices + 16));
b3 = u64x8_from_u32x8 (u32x8_load_unaligned (indices + 24));
u64x8_store_unaligned ((b0 << shift) + off, ptrs);
u64x8_store_unaligned ((b1 << shift) + off, ptrs + 8);
u64x8_store_unaligned ((b2 << shift) + off, ptrs + 16);
u64x8_store_unaligned ((b3 << shift) + off, ptrs + 24);
ptrs += 32;
indices += 32;
n_elts -= 32;
}
if (n_elts >= 16)
{
b0 = u64x8_from_u32x8 (u32x8_load_unaligned (indices));
b1 = u64x8_from_u32x8 (u32x8_load_unaligned (indices + 8));
u64x8_store_unaligned ((b0 << shift) + off, ptrs);
u64x8_store_unaligned ((b1 << shift) + off, ptrs + 8);
ptrs += 16;
indices += 16;
n_elts -= 16;
}
if (n_elts >= 8)
{
b0 = u64x8_from_u32x8 (u32x8_load_unaligned (indices));
u64x8_store_unaligned ((b0 << shift) + off, ptrs);
ptrs += 8;
indices += 8;
n_elts -= 8;
}
if (n_elts == 0)
return;
b0 = u64x8_from_u32x8 (u32x8_load_unaligned (indices + n_elts - 8));
u64x8_store_unaligned ((b0 << shift) + off, ptrs + n_elts - 8);
}
else
{
u32 mask = pow2_mask (n_elts);
u64x8 r = u64x8_from_u32x8 (u32x8_mask_load_zero (indices, mask));
u64x8_mask_store ((r << shift) + u64x8_splat ((u64) base), ptrs, mask);
return;
}
#elif defined CLIB_HAVE_VEC256
if (n_elts >= 4)
{
u64x4 off = u64x4_splat ((u64) base);
u64x4 b0, b1, b2, b3, b4, b5, b6, b7;
while (n_elts >= 32)
{
b0 = u64x4_from_u32x4 (u32x4_load_unaligned (indices));
b1 = u64x4_from_u32x4 (u32x4_load_unaligned (indices + 4));
b2 = u64x4_from_u32x4 (u32x4_load_unaligned (indices + 8));
b3 = u64x4_from_u32x4 (u32x4_load_unaligned (indices + 12));
b4 = u64x4_from_u32x4 (u32x4_load_unaligned (indices + 16));
b5 = u64x4_from_u32x4 (u32x4_load_unaligned (indices + 20));
b6 = u64x4_from_u32x4 (u32x4_load_unaligned (indices + 24));
b7 = u64x4_from_u32x4 (u32x4_load_unaligned (indices + 28));
u64x4_store_unaligned ((b0 << shift) + off, ptrs);
u64x4_store_unaligned ((b1 << shift) + off, ptrs + 4);
u64x4_store_unaligned ((b2 << shift) + off, ptrs + 8);
u64x4_store_unaligned ((b3 << shift) + off, ptrs + 12);
u64x4_store_unaligned ((b4 << shift) + off, ptrs + 16);
u64x4_store_unaligned ((b5 << shift) + off, ptrs + 20);
u64x4_store_unaligned ((b6 << shift) + off, ptrs + 24);
u64x4_store_unaligned ((b7 << shift) + off, ptrs + 28);
ptrs += 32;
indices += 32;
n_elts -= 32;
}
if (n_elts == 0)
return;
if (n_elts >= 16)
{
b0 = u64x4_from_u32x4 (u32x4_load_unaligned (indices));
b1 = u64x4_from_u32x4 (u32x4_load_unaligned (indices + 4));
b2 = u64x4_from_u32x4 (u32x4_load_unaligned (indices + 8));
b3 = u64x4_from_u32x4 (u32x4_load_unaligned (indices + 12));
u64x4_store_unaligned ((b0 << shift) + off, ptrs);
u64x4_store_unaligned ((b1 << shift) + off, ptrs + 4);
u64x4_store_unaligned ((b2 << shift) + off, ptrs + 8);
u64x4_store_unaligned ((b3 << shift) + off, ptrs + 12);
ptrs += 16;
indices += 16;
n_elts -= 16;
}
if (n_elts >= 8)
{
b0 = u64x4_from_u32x4 (u32x4_load_unaligned (indices));
b1 = u64x4_from_u32x4 (u32x4_load_unaligned (indices + 4));
u64x4_store_unaligned ((b0 << shift) + off, ptrs);
u64x4_store_unaligned ((b1 << shift) + off, ptrs + 4);
ptrs += 8;
indices += 8;
n_elts -= 8;
}
if (n_elts > 4)
{
b0 = u64x4_from_u32x4 (u32x4_load_unaligned (indices));
u64x4_store_unaligned ((b0 << shift) + off, ptrs);
ptrs += 4;
indices += 4;
n_elts -= 4;
}
b0 = u64x4_from_u32x4 (u32x4_load_unaligned (indices + n_elts - 4));
u64x4_store_unaligned ((b0 << shift) + off, ptrs + n_elts - 4);
return;
}
#ifdef CLIB_HAVE_VEC256_MASK_LOAD_STORE
else
{
u32 mask = pow2_mask (n_elts);
u64x4 r = u64x4_from_u32x4 (u32x4_mask_load_zero (indices, mask));
u64x4_mask_store ((r << shift) + u64x4_splat ((u64) base), ptrs, mask);
return;
}
#endif
#elif defined(CLIB_HAVE_VEC128)
if (n_elts >= 4)
{
u64x2 ov = u64x2_splat ((u64) base);
u32 *i = (u32 *) indices;
void **p = (void **) ptrs;
u32 n = n_elts;
while (n >= 32)
{
clib_index_to_ptr_u32x4 (indices, ptrs, 0, ov, shift);
clib_index_to_ptr_u32x4 (indices, ptrs, 4, ov, shift);
clib_index_to_ptr_u32x4 (indices, ptrs, 8, ov, shift);
clib_index_to_ptr_u32x4 (indices, ptrs, 12, ov, shift);
clib_index_to_ptr_u32x4 (indices, ptrs, 16, ov, shift);
clib_index_to_ptr_u32x4 (indices, ptrs, 20, ov, shift);
clib_index_to_ptr_u32x4 (indices, ptrs, 24, ov, shift);
clib_index_to_ptr_u32x4 (indices, ptrs, 28, ov, shift);
indices += 32;
ptrs += 32;
n -= 32;
}
if (n == 0)
return;
if (n >= 16)
{
clib_index_to_ptr_u32x4 (indices, ptrs, 0, ov, shift);
clib_index_to_ptr_u32x4 (indices, ptrs, 4, ov, shift);
clib_index_to_ptr_u32x4 (indices, ptrs, 8, ov, shift);
clib_index_to_ptr_u32x4 (indices, ptrs, 12, ov, shift);
indices += 16;
ptrs += 16;
n -= 16;
}
if (n >= 8)
{
clib_index_to_ptr_u32x4 (indices, ptrs, 0, ov, shift);
clib_index_to_ptr_u32x4 (indices, ptrs, 4, ov, shift);
indices += 8;
ptrs += 8;
n -= 8;
}
if (n > 4)
clib_index_to_ptr_u32x4 (indices, ptrs, 0, ov, shift);
clib_index_to_ptr_u32x4 (i, p, n_elts - 4, ov, shift);
return;
}
#endif
while (n_elts)
{
ptrs[0] = base + ((u64) indices[0] << shift);
ptrs += 1;
indices += 1;
n_elts -= 1;
}
}
#endif