ARM NEON内在函数中的逆向量顺序

use*_*328 4 arm intrinsics neon

我试图颠倒128位向量(uint16x8)的顺序.

例如,如果我有

a b c d e f g h
Run Code Online (Sandbox Code Playgroud)

我想获得

h g f e d c b a
Run Code Online (Sandbox Code Playgroud)

使用NEON内在函数有一种简单的方法吗?我尝试使用VREV,但它不起作用.

aus*_*len 6

您需要vrev64.16指令,但它不会在单个四重寄存器的双寄存器之间交换.您需要使用额外的功能来实现这一目标vswp.

对于内在的

q = vrev64q_u16(q)
Run Code Online (Sandbox Code Playgroud)

应该在双字内部交换技巧,然后你需要交换quad寄存器中的双字.然而,这很麻烦,因为没有vswp直接的内在因素迫使你使用类似的东西

q = vcombine_u16(vget_high_u16(q), vget_low_u16(q))
Run Code Online (Sandbox Code Playgroud)

实际上最终作为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;
}
Run Code Online (Sandbox Code Playgroud)

它生成如下所示的程序集

vld1.16 {d16-d17}, [sp:64]
movs    r4, #0
vrev64.16   q8, q8
vswp    d16, d17
vst1.16 {d16-d17}, [r5]
Run Code Online (Sandbox Code Playgroud)

和产出

$ rev
0x108 0x107 0x106 0x105 0x104 0x103 0x102 0x101
Run Code Online (Sandbox Code Playgroud)