aarch64 neon指令集拾遗

太常用就不列出了。


读写指令

读向量/浮点数

ld1

ld1 {v0.S}[0], [x0], #4从x0出读一个float数,存到v0寄存器的第一个通道,并将x0加4

ld1 {v0.4S, v1.4S...}, [x0] 从x0处连续读入float,依次存到各个寄存器中

ld1 {v0.8B, v1.8B}, [x0] ld1不仅可以读128位向量寄存器,也可以读64位向量寄存器,此时每个寄存器的高64位都是0,这样就可以处理8位向量

需要注意的是,ld1 是可以连续读浮点数到同一个vector中的,即:

ld1 {v0.S}[0], [x0], #4 
ld1 {v0.S}[1], [x0], #4

ldr ldrb ldrh 区别

可以参考此文
ldrb R0, R1 从R1地址读一个字节存到R0,且将R0高位置为0。

ldrb w5, [x0], #1 //读一个字节
ldrb w6, [x1], #1 //读一个字节
add  w7, w5, w6   //加
strb w7, [x2], #1 //存一个字节

相应地,ldrh和strh就是处理16位整数

ld1r

一个很好用的指令,从[x1]读一个元素,并赋值到向量所有通道
ld1r {v4.4S}, [x1], #4
偏移和元素有关的,具体如下:

Type imm
8B/16B 1
4H/8H 2
2S/4S 4
D/2D 8

加法指令

UADDL, UADDL2 为了解决溢出问题,可以用长指令

UADDL{2} <Vd>.<Ta>, <Vn>.<Tb>, <Vm>.<Tb>
这两个长指令都是为了完成无符号整数的加法,不同的是,UADDL,是对两个源向量的低64位中的元素进行相加,并将长度增加2倍,写到目标寄存器中;UADDL2,是对高64位进行elemnetwise相加,并将结果写会目标寄存器。

ld1 {v0.16B}, [x0], #16
ld1 {v1.16B}, [x1], #16
uaddl  v6.8H, v0.16B, v1.16B  // 低64位,低位的8个数相加
uaddl2 v7.8H, v0.18B, v1.16B  // 高64位

uqadd 饱和加

ld1 {v0.16B}, [x0], #16
ld1 {v1.16B}, [x1], #16
uqadd v2.16B, v0.16B, v1.16B

乘法

fmla 浮点乘加指令

在计算过程中是最强大最实用的指令了,有三大类场景

  • 两个浮点数相乘,并与目标浮点寄存器相加 FMLA <Hd>, <Hn>, <Vm>.H[<index>]
  • 向量与单个元素相乘,并与目标向量相加 FMLA <Vd>.<T>, <Vn>.<T>, <Vm>.<Ts>[<index>]
  • 向量与向量逐个元素相乘,并与目标向量相加 FMLA <Vd>.<T>, <Vn>.<T>, <Vm>.<T>

乘法支持16bit、32bit以及64bit,举例:

fmla H1, H0, {v3.H}[0]
fmla v2.4S, v1.4S, {v0.S}[0]
fmla v2.4S, v1.4S, v0.4S

mla 无符号整数乘加指令

所以不支持64位!
其他用法与fmla类似。

发布了42 篇原创文章 · 获赞 33 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/gaussrieman123/article/details/96150214