Je constate 4 octets chargés dans un registre neon. Comment puis-je convertir efficacement cela en 12 bits, par exemple j'ai besoin d'insérer 4 bits nuls après le premier octet, 8 bits nuls après le deuxième, et ainsi de suite. Par exemple, si j'avais ces 4 octets en hexadécimal:
01 02 03 04
Cela se terminerait avec cela en hexadécimal:
01 20 00 03 40
Même opération exprimée en tant que simple fonction c qui opère sur une variable de 32 bits représentant les 4 octets d'entrée:
uint64_t expand12(uint32_t i)
{
uint64_t r = (i & 0xFF);
r |= ((i & 0x0000ff00) << 4); // décaler le deuxième octet de 4 bits
r |= ((i & 0x00ff0000) << 8); // décaler le troisième octet de 8 bits
r |= (((uint64_t)(i & 0xff000000)) << 12); // 4ème de 12
return r;
}
Donc, si j'ai ces octets dans un registre neon uint8x8_t
, quelle serait une bonne façon de mettre en œuvre la même opération en neon de sorte que le même registre se termine avec ces valeurs décalées?
Remarque, que les quatre octets ont des zéros dans les 4 bits supérieurs si cela aide d'une quelconque manière.
Mise à jour: Dans mon cas, j'ai 4 registres uint16x8_t et pour chacun je dois calculer la somme de toutes les voies (vaddv_u16
), puis effectuer vclz_u16
sur cette somme et ensuite combiner ces quatre sommes dans un registre neon en les plaçant à 12 bits d'intervalle:
uint64_t compute(uint16x8_t a, uint16x8_t b, uint16x8_t c, uint16x8_t d)
{
u16 a0 = clz(vaddv(a));
u16 b0 = clz(vaddv(b));
u16 c0 = clz(vaddv(c));
u16 d0 = clz(vaddv(d));
return (a0 << 36) | (b0 << 24) | (c0 << 12) | (d0);
}
Remarque, il s'agit d'un pseudo-code et j'ai besoin du résultat dans un registre neon.
Au cas où cela importe, dans mon code j'ai une fonction qui trouve les indices des éléments max dans 4 registres uint16x8_t. Dans cette fonction, ces quatre registres sont vand
és avec l'élément max dupliqué sur toutes les voies et ensuite le résultat a été vorr
é avec le masque de bits {1<<15, 1<<14, ... 1<<0}
; Ensuite, j'effectue l'addition par paire de toutes les voies et le clz de cela me donne l'index de l'élément max de chaque registre. Tout cela doit être entrelacé avec 4 bits nuls supplémentaires insérés entre les éléments et stockés dans un registre neon. Exemple en C:
void compute(uint16_t *src, uint64_t* dst)
{
uint64_t x[4];
for (int i = 0; i < 4; ++i, src+=16)
{
int max = 0;
for (int j = 0; j < 16; ++j)
{
if (src[j] > src[max])
max = j;
}
x[i] = max;
}
*dst = (x[0] << 36) | (x[1] << 24) | (x[2] << 12) | (x[3]);
}
Cette fonction fait partie d'une grande fonction qui effectue ce calcul des millions de fois dans une boucle et les résultats de cette fonction sont utilisés et doivent être dans un registre neon. Considérez-le comme du pseudo-code qui décrit l'algorithme, s'il n'est pas clair ce que cela signifie: cela signifie que seul l'algorithme importe, il n'y a pas de charges ou de stockages qui doivent être optimisés