在霓虹灯寄存器中添加

Posted

技术标签:

【中文标题】在霓虹灯寄存器中添加【英文标题】:Addition in neon register 【发布时间】:2012-07-17 05:45:10 【问题描述】:

假设我在 neon 中有一个 64 位的 d 寄存器。假设它存储值 ABCDEFGH。 现在我想添加 A&E、B&F、C&G、D&H 等等。这里有任何内在的东西可以进行这样的操作

我查看了文档,但没有找到合适的内容。

【问题讨论】:

这是什么“等等”?你能具体说明你想要达到的目标吗? 其实我在做一些图像处理操作。我的图像是 RGBA 格式。我想添加两个连续像素的 r,g,b 和 a 分量。 另外,最初我尝试使用 vld4q 加载数据并使用成对加法。但是在一次操作中,所有 16 个寄存器都被使用,出现了一个错误。 vld4q_u8 将使用 4 个 q 寄存器。即使在最坏的情况下,添加和存储它们也需要 2 个以上的 q 寄存器。还剩下 10 个寄存器。!你是如何编写代码来使用所有 16 个寄存器来实现这样一个简单的算法的!如果您可以分享您尝试过的代码会更好。它还将帮助我们向您建议最好的编写方式。 有多种方法可以做你想做的事,但你究竟想要怎样添加?您想要 16 位结果吗?还是您想要饱和的 8 位结果?如果是饱和有符号或无符号? 【参考方案1】:

如果您希望以 16 位执行加法,即产生 uint16x4 结果,您可以使用 vmovl 将输入向量从 uint8x8 提升为 uint8x16,然后使用 vadd 将下半部分和上半部分相加。用 NEON 内在函数表示,这是通过

const int16x8_t t = vmovl_u8(input);
const int16x4_t r = vadd_u16(vget_low(t), vget_high(t))

这应该编译为以下程序集(d0 是 64 位输入寄存器,d1 是 64 位输出寄存器)。注意 vget_low 和 vget_high 不产生任何指令——这些内在函数是通过适当的寄存器分配实现的,通过利用 Q 寄存器只是命名两个连续 D 寄存器的便捷方式。 Qn 指的是对 (D2n, D2n+1)。

VMOVL.U8 q1, d0
VADD.I16 d1, d2

如果您希望操作以 8 位执行,并在溢出的情况下饱和,请执行

const int8x8_t t = vreinterpret_u8_u64(vshr_n_u64(vreinterpret_u64_u8(input), 32));
const int8x8_t r = vqadd_u8(input, t);

这编译为(d0再次作为输入,在d1中输出)

VSHR.U64 d1, d0, #32
VQADD.I8 d1, d0

通过仅用 VADD 替换 VQADD,结果将在溢出时回绕,而不是饱和到 0xff。

【讨论】:

以上是关于在霓虹灯寄存器中添加的主要内容,如果未能解决你的问题,请参考以下文章

将一种形式的霓虹灯寄存器转换为另一种可能吗

如何编程霓虹灯寄存器索引

如何在具有霓虹内在函数的多核处理器中有效地使用所有霓虹灯单元

如何清除霓虹灯中除第一个非零车道之外的所有车道?

SSE 到霓虹灯 (_mm_movelh_ps)

影响标志的霓虹汇编向量指令