Я пытаюсь изменить порядок 128-битного вектора (uint16x8).

Например, если у меня есть

a b c d e f g h

Я бы хотел получить

h g f e d c b a

Есть ли простой способ сделать это с помощью встроенных функций NEON? Я пробовал использовать VREV, но он не работает.

4
user1926328 12 Сен 2013 в 13:44
1
Как вы пробовали vrev?
 – 
auselen
12 Сен 2013 в 13:54

1 ответ

Лучший ответ

Вам нужна инструкция vrev64.16, однако она не переключается между двойными регистрами одного четверного регистра. Вам нужно добиться этого с помощью дополнительного vswp.

Для внутренних

q = vrev64q_u16(q)

Должен сделать трюк для замены внутри двойных слов, тогда вам нужно поменять местами двойные слова в четверном регистре. Однако это становится обременительным, поскольку нет никаких встроенных функций vswp, которые вынуждают вас использовать что-то вроде

q = vcombine_u16(vget_high_u16(q), vget_low_u16(q))

Что фактически заканчивается инструкцией vswp.

См. Пример ниже.

#include <stdio.h>
#include <stdlib.h>
#include <arm_neon.h>

int main() {
    uint16_t s[] = {0x101, 0x102, 0x103, 0x104, 0x105, 0x106, 0x107, 0x108};
    uint16_t *t = malloc(sizeof(uint16_t) * 8);
    for (int i = 0; i < 8; i++) {
        t[i] = 0;
    }
    uint16x8_t a = vld1q_u16(s);
    a = vrev64q_u16(a);
    a = vcombine_u16(vget_high_u16(a), vget_low_u16(a));
    vst1q_u16(t, a);
    for (int i = 0; i < 8; i++) {
        printf("0x%3x ", t[i]);
    }
    printf("\n");
    return 0;
}

Который генерирует сборку, как показано ниже

vld1.16 {d16-d17}, [sp:64]
movs    r4, #0
vrev64.16   q8, q8
vswp    d16, d17
vst1.16 {d16-d17}, [r5]

И выводы

$ rev
0x108 0x107 0x106 0x105 0x104 0x103 0x102 0x101
6
auselen 12 Сен 2013 в 16:14