【问题标题】:ARM NEON Assembler - usage & understandingARM NEON 汇编器 - 用法和理解
【发布时间】:2012-02-16 17:36:15
【问题描述】:

我是汇编程序和 NEON 编程的新手。 我的任务是使用 NEON 指令将部分算法从 C 转换为 ARM 汇编程序。 该算法采用一个 int32 数组,从该数组加载不同的值,进行一些位移和异或并将结果写入另一个数组。 稍后我将使用具有 64 位值的数组,但现在我只是尝试重写代码。

C Pseudo code:

out_array[index] = shiftSome( in_array[index] ) ^ shiftSome( in_array[index] );

以下是我关于 NEON 说明的问题:

1.) 如果我加载这样的寄存器:

vld1.32 d0, [r1]

它会仅从内存中加载 32 位还是 2x32 位来填充 64 位 Neon D 寄存器?

2.) 如何访问 D-Register 的 2/4/8(i32、i16、i8)部分?

3.) 我正在尝试从具有偏移量的数组中加载不同的值,但它没有 似乎工作......我做错了什么......这是我的代码: (它是一个整数数组,所以我试图加载例如 3 元素,其偏移量应为 64Bit = 8 字节)

asm volatile(
"vld1.32 d0, [%0], #8 \n"     
"vst1.32 d0, [%1]" : : "r" (a), "r" (out): "d0", "r5");

其中“a”是数组,“out”是指向整数的指针(用于调试)。

4.) 从数组中加载一个值后,我需要将其向右移动,但它似乎不起作用:

vshr.u32 d0, d0, #24     // C code:   x >> 24;

5.) 是否可以只在 Neon 寄存器中加载 1 个字节,这样我就不必移动/屏蔽某些东西来只获得我需要的一个字节?

6.) 我需要使用内联汇编器,但我不确定最后一行是做什么用的:

input list : output list : what is this for?

7.) 你知道任何带有代码示例的好的 NEON 参考资料吗?

程序应该在三星 Galaxy S2、cortex-A9 处理器上运行,如果这有什么不同的话。感谢您的帮助。

----编辑-------

这是我发现的:

  1. 它将始终加载完整的寄存器(64 位)
  2. 您可以使用“vmov”指令将 Neon 寄存器的一部分传输到 arm 寄存器。
  3. 偏移量应该在一个臂寄存器中,并将添加到 基址内存访问之后。
  4. 它是“被破坏的注册列表”。使用的每个寄存器和 无论是输入还是输出列表,都应该写在这里。

【问题讨论】:

  • 2.将内容从 SIMD 寄存器移动到 ARM 寄存器将导致完整的流水线刷新,大约需要 14 个周期。避免它。

标签: android assembly arm neon armv6


【解决方案1】:

我可以回答你的大部分问题:(更新:澄清“车道”问题)

1) NEON 指令一次只能在内存中加载和存储整个寄存器(64 位、128 位)。有一个 MOV 指令变体,允许将单个“通道”移入或移出 ARM 寄存器。

2) 您可以使用 NEON MOV 指令来影响单通道。执行过多的单元素操作时,性能会受到影响。 NEON 指令通过对向量(浮点数/整数组)执行并行操作来提高应用程序性能。

3) ARM 汇编语言中的立即数偏移量是字节,而不是元素/寄存器。 NEON 指令允许使用寄存器进行后增量,而不是立即值。对于普通的 ARM 指令,您的 8 后增量将为源指针添加 8(字节)。

4) NEON 中的移位会影响向量的所有元素。使用 vshr.u32 右移 24 位会将 32 位无符号长整数移位 24 位并丢弃移出的位。

5) NEON 指令允许将单个元素移入和移出普通 ARM 寄存器,但不允许从内存直接加载或存储到“通道”。

6) ?

7) 从这里开始:http://blogs.arm.com/software-enablement/161-coding-for-neon-part-1-load-and-stores/ ARM 网站上有一个很好的 NEON 教程。

【讨论】:

  • 关于 1 和 5:可以在 NEON 寄存器中加载和存储单个元素。只需在 NEON 寄存器后用 [] 指定元素索引。例如,可以使用相同的符号将一个向量与另一个向量中的单个元素相乘。
  • 完全正确,除了后增量。您不能使用 NEON 添加即时值作为后增量。您可以使用寄存器 ARM 寄存器来执行此操作或使用!这将增加读取数据的大小。
【解决方案2】:

6) 破坏寄存器。

asm(code : output operand list : input operand list : clobber list);

如果您使用的寄存器没有作为操作数传递,您需要告知 关于这个的编译器。以下代码将一个值调整为四的倍数。它 使用 r3 作为临时寄存器,并通过在 破坏者名单。此外,CPU 状态标志由 ands 指令修改。 将伪寄存器 cc 添加到 clobber 列表将使编译器随时了解 这个修改也是如此。

asm (
"ands R3, %1, #3"
"eor %0, %0, r3"
: "=r"(len)
: "0"(len)
: "cc", "r3"
);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-01
    • 1970-01-01
    相关资源
    最近更新 更多