在霓虹灯寄存器中添加
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。
【讨论】:
以上是关于在霓虹灯寄存器中添加的主要内容,如果未能解决你的问题,请参考以下文章