NEON的​​​​​​​Registers, vectors, lanes and elements

NEON的Registers, vectors, lanes and elements

NEON指令和浮点指令使用相同的寄存器文件,称之为“NEON和浮点寄存器文件”。

它跟ARM core 寄存器文件完全区分开。NEON和浮点寄存器文件是一组可以作为32-bit、64-bit或128-bit的寄存器来访问。对于一个指令,哪个寄存器是可用的依赖于它是一个NEON指令还是一个VFP指令。本文把NEON和浮点寄存器作为NEON寄存器。一些VFP和NEON指令在通用寄存器和NEON寄存器之间移动数据,或使用ARM通用寄存器来寻址内存。

NEON寄存器的内存是相同数据类型的元素向量。一个向量被分割成通道(lanes),每个通道包含一个数值,称之为“元素”。

通常,每个NEON指令会并行执行n个操作,这里的n是输入向量分割成的通道的个数。每个操作包含在通道内。不会考虑到一个通道到另一个通道间的进位或溢出。

一个NEON向量的通道的个数依赖于向量的大小和向量中的数值元素:

  1. 64-bitNEON向量可以包含:
  1. 8x8-bit
  2. 4x16-bit
  3. 2x32-bit
  4. 1x64-bit
  1. 128-bitNEON向量可以包含:
  1. 16x8-bit
  2. 8x16-bit
  3. 4x32-bit
  4. 2x64-bit

元素排序

图1-1 显示了向量中的元素的排序,从最低位开始。这意味着,元素0使用了寄存器的最低有效位。

图 1-1  元素与通道

图 1-2显示了 VADD.I16 Q0, Q1, Q2 指令是如何并行执行Q1和Q2内的8x16-bit整数add操作,把结果保存到Q0中。

图 1-2  8 way 16-bit integer add operation

​​​​​​​Register overlap

图 1-3 显示NEON和浮点寄存器文件,寄存器怎样重叠的。

NEON单元把寄存器文件看作:

  1. 16个 128-bit Q,或 4字,寄存器,Q0-Q15。
  2. 32个64-bit D,或双字,寄存器,D0-D31。(16个 64-bit D 寄存器VFPv3-D16)。

D寄存器的映射为:

  1. D<2n>映射为Q<n>的低半部分;
  2. D<2n+1>映射为Q<n>的高半部分;
  1. Q和D寄存的结合
  2. NEON单元寄存器不能直接访问一个32-bit VFP S寄存器。见NEON和浮点寄存器文件的VFP 角度。
  1.  S<2n>映射到 D<n>的低半部分;
  2. S<2n+1>映射到D<n>的高半部分。

图 1-3   NEON and floating-point register file

所有这些寄存器在任何时候都能访问。软件并不需要精确地在它们之间切换,因为使用的指令会决定合适的view。

在图 1-4 中,S\D和Q寄存器是相同寄存器Q0的不同view。:

  1. NEON单元可以把Q0作为一个128-bit寄存器访问。
  2. NEON单元可以把Q0作为2个连续的64-bit寄存器D0和D1来访问。
  3. NEON单元不能单独把Q0作为32-bit S 寄存器访问。如果存在VFP单元,可以把它当作S0、S1、S2和S3来访问。

图 1-4   Register overlap

​​​​​​​Scalar data

标量数据是指一个单一数值,而不是一个包含多个值的向量。一些NEON指令使用一个标量操作符。一个寄存器内的标量可以通过到向量的index来访问。用于访问向量的单个元素的数组标识是 Dm[x]或 Qm[x],其中, x是向量 Dm或 Qm的索引。

指令  VMOV.8 D0[3], R3  移动寄存器R3中的最低有效字节到寄存器D0的第四个字节中。

图 1-5  Moving a scalar to a lane

NEON标量可以是8-bit、16-bit、32-bit或64-bit值。与乘法指令不同,访问标量的指令可以访问寄存器文件中的任何元素。

乘法指令只能允许16-bit或32-bit标量,并且只能访问寄存器文件中的前32个标量:

  1. 16-bit标量限制在寄存器 D0[x]-D7[x],x的范围是0到3。
  2. 32-bit标量限制在寄存器 D0[x]-D15[x],x的范围是0到1.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
NEON是ARM架构中的一种SIMD(单指令多数据)技术,它可以在同一时钟周期内对多个数据进行并行处理,从而提高数据处理的效率。在NEON中,可以使用NEON寄存器来加速拷贝操作。 对于NEON拷贝,有两个引用内容提供了相关的函数实现。其中,引用给出了一个用NEON寄存器进行加速拷贝的函数memcpy_neon_64,它一次可以拷贝64字节,并适用于64字节的对齐拷贝。函数实现的伪代码如下: ```assembly void* memcpy_neon_64(void* dest, const void* src, size_t size) { mov r3, r0 // 保存返回值 0: PLD(pld [r1, #256]) // 预取数据 subs r2, r2, #64 // 计算剩余拷贝大小 vldmia.64 r1!, {d0-d7} // 从源地址加载数据到寄存器 vstmia.64 r0!, {d0-d7} // 将寄存器中的数据存储到目标地址 bgt 0b // 如果还有剩余数据,则继续循环 mov r0, r3 // 将返回值保存到r0寄存器中 mov pc, lr // 退出函数 } ``` 另外,引用提供了另一种实现方式,函数memcpy_1一次只拷贝一个字节,可用于对齐拷贝和非对齐拷贝。函数实现的伪代码如下: ```c void *memcpy_1(void *dest, const void *src, size_t count) { char *tmp = dest; const char *s = src; while (count--) *tmp++ = *s++; return dest; } ``` 如果你想要了解更多关于NEON指令的使用方法,可以参考GCC官方文档中的ARM NEON Intrinsics页面[3]。 综上所述,NEON memcpy是利用NEON寄存器来加速拷贝操作的一种技术,可以一次拷贝多个字节,提高数据处理效率。可以根据需求选择适合的NEON拷贝函数进行使用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值