Memory 手臂霓虹灯:什么';vld4_f32和vld4q_f32的区别是什么?

Memory 手臂霓虹灯:什么';vld4_f32和vld4q_f32的区别是什么?,memory,assembly,arm,neon,cpu-registers,Memory,Assembly,Arm,Neon,Cpu Registers,我无法区分ARM霓虹灯指令中的vld4_f32和vld4q_f32之间的区别 当我提高编码级别,开始查看汇编指令而不是信息量较小的内部函数时,开始出现混乱 我需要在这里使用vld4变量指令的原因是,我想从我的大数组的每个4位置捕获4float32\t vld4_f32intrinsic和相应的组装说明如下所示() vld4q_f32intrinsic及其相应的汇编指令如下所示 float32x4x4_t vld4q_f32 (const float32_t *) Form of expect

我无法区分ARM霓虹灯指令中的
vld4_f32
vld4q_f32
之间的区别

当我提高编码级别,开始查看汇编指令而不是信息量较小的内部函数时,开始出现混乱

我需要在这里使用vld4变量指令的原因是,我想从我的大数组的每个4位置捕获4
float32\t

vld4_f32
intrinsic和相应的组装说明如下所示()

vld4q_f32
intrinsic及其相应的汇编指令如下所示

float32x4x4_t vld4q_f32 (const float32_t *) 
Form of expected instruction(s): vld4.32 {d0, d1, d2, d3}, [r0]
嗯,在intrinsic级别上,我看到的区别是返回类型,但是如果我看汇编指令和寄存器的数量,它们看起来都一样。编译器或汇编程序如何知道两者之间的区别


是否有人能对此进行进一步澄清,并解释如何将位于每4个内存位置的值加载到单个寄存器中?

是的,我发现了差异。我使用CodeSourcery查看所有加载指令的实际寄存器内容。我发布的链接没有给出vld4q_f32的完整细节

好的,首先是
vld4_f32
,这将加载4d寄存器(例如d16-19),每个d寄存器的长度为64位,因此此指令将加载以4为间隔交错的前8个值,如下图所示。

在第二种情况下,
vld4q_f32
,这将加载8d寄存器(例如d16-23),而不是四个。对于这种类型的读取器,是否加载8个寄存器一点也不清楚。当我查看vld4qf32的分解代码时,它使用的是8D寄存器

此指令确实会执行我希望它执行的操作,即加载间隔为4的4
float32\t
值,如下图所示。

我已经分解了两个本质,也许它对某人有帮助:

// C++
uint32x4x4_t r = vld4q_u32( ( uint32_t *) output );
// assembly
VLD4.32         {D16,D18,D20,D22}, [R0]!
VLD4.32         {D17,D19,D21,D23}, [R0]

// C++
uint32x2x4_t r = vld4_u32( ( uint32_t *) output );
// assembly
VLD4.32         {D20-D23}, [R0]

嗯,vld4q加载4个q寄存器,顾名思义…
// C++
uint32x4x4_t r = vld4q_u32( ( uint32_t *) output );
// assembly
VLD4.32         {D16,D18,D20,D22}, [R0]!
VLD4.32         {D17,D19,D21,D23}, [R0]

// C++
uint32x2x4_t r = vld4_u32( ( uint32_t *) output );
// assembly
VLD4.32         {D20-D23}, [R0]