文章目录
- SVE Load 和 Store 指令使用介绍
- LD1 加载指令
- ST1 存储指令
- PFR 预取指令
- 参考示例
- LD1 加载示例
- ST1 存储示例
- 代码实例
SVE Load 和 Store 指令使用介绍
ARMv9架构中的SVE(Scalable Vector Extension)指令集为向量计算提供了强大支持,特别是针对不同数据类型和访问模式的加载(Load)和存储(Store)操作。下面是对您提到的一些SVE指令的简要介绍和使用示例。
LD1 加载指令
LD1{B|D|H|W} {Zt.<T>}, Pg/Zn, [Xn, Xm{, LSL #imm}]:- 加载一个或多个元素到向量寄存器
Zt中。 {B|D|H|W}指定加载的元素大小(字节、双字、半字、字)。Pg/Zn为谓词寄存器,控制加载操作。[Xn, Xm{, LSL #imm}]指定内存地址。
- 加载一个或多个元素到向量寄存器
LD1R{B|D|H|W} {Zt.<T>}, Pg/Zn, [Xn]:- 从内存加载一个元素并重复到向量
Zt的所有元素中。 R代表重复(Repeat)。
- 从内存加载一个元素并重复到向量
LD1RO{B|D|H|W} {Zt.<T>}, Pg/Zn, [Xn, Xm]:- 从内存加载一个旋转(Rotate)元素到向量
Zt中。 RO代表旋转(Rotate)。
- 从内存加载一个旋转(Rotate)元素到向量
LDFF1{B|H|W|D} {Zt.<T>}, Pg/Zn, [Xn, Xm]:- 第一次找到的(First-Fault)加载。如果遇到不能访问的内存,则停止加载剩余元素。
FF代表第一次遇到故障就停止。
ST1 存储指令
ST1{B|D|H|W} {Zt.<T>}, Pg, [Xn, Xm{, LSL #imm}]:- 将向量寄存器
Zt中的一个或多个元素存储到内存。 - 用法类似于加载指令,但用于存储。
- 将向量寄存器
PFR 预取指令
PRF{B|D|H|W}:- 预取指令用于将内存数据预取到高速缓存,以提高访问速度。
- 指定预取的数据大小和类型。
参考示例
假设我们需要将一个双字(64位)的数据加载到向量寄存器Z0中,然后将这个向量的数据存储回内存。
LD1 加载示例
// 假设X0包含了数据的内存地址
// 使用Pg作为谓词寄存器,控制加载过程
ptrue p0.d
// 从[X0]地址加载一个双字数据到Z0的所有元素中
ld1rd {z0.d}, p0, [x0]
这里,ld1rd指令从X0指向的内存地址加载一个双字数据,并将其重复填充到向量寄存器Z0的所有元素中,受谓词寄存器P0的控制。
ST1 存储示例
// 假设X1包含了要存储数据的目标内存地址
// 将Z0寄存器中的数据存储到[X1]地址
st1d {z0.d}, p0, [x1]
这里,st1d指令将向量寄存器Z0中的数据存储到X1指向的内存地址中,操作受谓词寄存器P0的控制。
代码实例
测试代码如下:
- 首先将谓词寄存器
p0中所有字节元素的控制位都设为1,意味着所有后续操作都会影响到z0的所有字节元素; - 执行
ST1B {z0.d}, p0, [x1]按8位(即1字节)的单元将z0寄存器中的数据(根据谓词寄存器p0的掩码)存储到x1指向的开始地址0xb0000000处; - 最后将地址
0xb0000000地址处的值返回。
func sve_add_test
stp x29, x30, [sp, #-0x10]!
ptrue p0.b
ldr w0, =0x11111111
dup z0.b, w0
cpy z0.b, p0/z, #0x55
ldr x1, =0xb0000000
st1b {z0.d}, p0, [x1]
mov x0, xzr
ldr x0, [x1]
ldp x29,x30, [sp], #0x10
ret
endfunc sve_add_byte_test
需要注意的是 指令 ST1{B|D|H|W} 写的次数是和 {z0.n} 的配置有关,比如当测试代码修改为 st1w {z0.d}, p0, [x1] 之后,表示每次写一个word,一共写2次,因为z0 向量寄存器的大小为128bits,在写入操作时每个元素的大小是按照64bits计算的。
msh >dump 0xb0000000 4
0xb0000000: 0x55555555 0x55555555 0x00000000 0x00000000
修改为 st1b {z0.d}, p0, [x1] 之后,在写入操作时每个元素的大小是按照64bits计算的,每次写1入byte:
msh >dump 0xb0000000 4
0xb0000000: 0x00005555 0x00000000 0x00000000 0x00000000
修改为 st1b {z0.b}, p0, [x1] 之后,在写入操作时每个元素的大小是按照8bits计算的,每次写1入byte:
msh >dump 0xb0000000 4
0xb0000000: 0x55555555 0x55555555 0x55555555 0x55555555
修改为 st1b {z0.h}, p0, [x1] 之后,在写入操作时每个元素的大小是按照16bits(half-word)计算的,每次写1入byte, 一共写入8次:
msh >dump 0xb0000000 4
0xb0000000: 0x55555555 0x55555555 0x00000000 0x00000000



















