2017-08-30 92 views
1

我正在看一些我们测试的ARM开发板的ARM反汇编。它们使用NEON固有的vld1q_u32使用-march=armv7-a -mfloat-abi=hard -mfpu=neon生产。vld1.32 {d20-d21}和vld1q q10之间的区别?

一个一个特定的机器与NEON我们看到(/proc/cpuinfo half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae evtstrm):

0: b5f0  push {r4, r5, r6, r7, lr} 
... 
20: f964 4a8f vld1.32 {d20-d21}, [r4] 

在另一NEON机,我们看到(/proc/cpuinfo : swp half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt):

0: e92d 4ff0  stmdb sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr} 
... 
28: f964 2a8f  vld1.32 {d18-d19}, [r4] 

而且一个ARMv8的机器,我们看到(/proc/cpuinfo : fp asimd evtstrm aes pmull sha1 sha2 crc32) :

0: 3dc00021  ldr  q1, [x1] 
... 
10: 3dc00c22  ldr  q2, [x1,#48] 
14: 3dc01023  ldr  q3, [x1,#64] 

我理解2-d和1- Q只是同一个bank of registers的不同观点。我不明白的是为什么ARMv7 NEON执行多寄存器加载而不是1Q加载。

我的问题是,vld1.32 {2-D}vld1q.32 1-Q之间有什么区别。或者为什么编译器不会在所有情况下生成1-Q加载?

回答

1

这里的区别在于32位ARM(aka AArch32)和AArch64。

2位寄存器混叠在一个Q寄存器中的事实在32位模式下是成立的,但在64位模式下不成立。在AArch64中,dXqX的前半部分,而不是q(X/2),如AArch32中所示,并且没有d寄存器名称用于寻址q寄存器的上半部分。

如果您在AArch32中汇编指令vld1.32 {q0}, [r0],它会变成与汇编vld1.32 {d0-d1}, [r0]时相同的操作码f920 0a8f(以拇指模式)。所以基本上由反汇编选择哪种形式更适合显示(虽然可能有反汇编指南,说它应该更喜欢使用D注册表)。

在AArch64上,这两种形式是不同的,因为寄存器没有以相同的方式进行别名化,所以如果你要求128位加载到Q寄存器,那就是你得到的,并且没有任何含糊之处。