c-ARM VFPv3汇编指令



我正在尝试调试TI am 3358 MCU中的一个非常低级别的数据故障。它来自浮点数学。

该系统使用TI RTOS、GNU 7.3.1编译器和VFPv3(VFP是编译器设置吗?FP数学库吗?我不清楚浮点代码的生成)。因此,尽管我有列出片段的反汇编,但修复需要在C代码级别。

这是一个由两部分组成的问题:

首先我能正确理解助记符吗?为什么有些没有列出?

我注意到反汇编的操作码没有助记符。这是一个列表片段,现在还不需要详细介绍。只需注意助记符丢失了,我不认为它们是即时数据(我在对编译的代码进行逆向工程时添加的注释):

8003ced0:   EEF1FA10            vmrs       apsr_nzcv, fpscr     ; Pull STAT reg to ARM MCU
8003ced4:   DA000041            ble        #0x8003cfe0          ;  branch less-equal to x0x...3cfe0
8003ced8:   EEFD7BE0           .word       0xeefd7be0          ; ???  What is this
8003cedc:   EDC47A0A            vstr       s15, [r4, #0x28]     ; Store S15 <-  r4+28 = st->f2.z
8003cee0:   E584702C            str        r7, [r4, #0x2c]      ; Store r7 <-  r4+2c = st->f2.a
8003cee4:   E3A03000            mov        r3, #0
8003cee8:   E5843030            str        r3, [r4, #0x30]
8003ceec:   EE07CA90            vmov       s15, r12             ; ( I decode this below)
8003cef0:   EEF80BE7           .word       0xeef80be7           ; ???
8003cef4:   EE702BA2           .word       0xee702ba2           ; ???
8003cef8:   EEFD7BE2           .word       0xeefd7be2           ; ???
8003cefc:   EDC47A0D            vstr       s15, [r4, #0x34]
8003cf00:   E5845018            str        r5, [r4, #0x18]
8003cf04:   EE701BA1           .word       0xee701ba1
8003cf08:   EEFD7BE1           .word       0xeefd7be1

为了确保我能理解VFPv3助记符,我将地址8002ceec解码为以下内容:

8003ceec:   EE07CA90            vmov       s15, r12
VMOV   (between ARM core register and single-precision register)
1110    unconditional
1110    
0000    opt = 0: so this is TO the VFP
0111    Vn = 7   (but still need one more bit from nibble 1)
1100    Rt = 12 
1010    
1001    N = 1  (so n = 01111  =S15)
0000

它来自https://developer.arm.com/documentation/ddi0406/c/Application-Level-Architecture/Instruction-Details/Alphabetical-list-of-instructions/VMOV--between-ARM-core-register-and-single-precision-register-?lang=en,(我很确定我得到了正确的,如果没有,欢迎任何更正)

那么,操作码0xeef80be7、0xee702ba2等是什么。?我无法在ARM书籍或网站中解读它们。遵循VFP/NEON模式,这是某种"无条件移动",但除此之外,我无法将比特模式与任何东西相匹配(而且网站对这种搜索非常不友好,我只能下载PDF并进行一点搜索)。

至于第二个问题,如果有一个简单明了的答案,我会很高兴被引导到正确的方向。

这是一个经过编译的C函数,它传递一个指向结构的指针。然后把成员从里面拉出来,做一些浮点运算。我确定结构地址存储在R4中。

示例原型是

int Function(int x, int y, struct *a);

并被称为(虚构的例子)

Function (5,5,&st[0]);

稍后在上

Function (5,7,&st[1]);

当访问第二个结构时,只有才会发生数据中止崩溃。访问第一个时从不使用。当VFP/Neon访问时,,而不是常规ARM寄存器。

进入代码的泥潭,R4是传入的结构的地址:

8003cfe0:   EEFD7BE0           .word       0xeefd7be0          ;  branch lands here 
8003cfe4:   EDC47A06            vstr       s15, [r4, #0x18]    ;  CRASH  Store S15 <-  r4+24 = st->f1.x
8003cfe8:   E584C01C            str        r12, [r4, #0x1c]    ;  r12 = st->f1.y
8003cfec:   E3A03000            mov        r3, #0
8003cff0:   E5843020            str        r3, [r4, #0x20]

我从指针中验证了成员的所有偏移,一切都是正确的。

重复,崩溃发生在地址8003cfe4,但仅当R4指针指向st[1]时,而从不在指向st[0]时。

我知道一个";数据中止";来自于尝试访问MMU未配置权限的内存。然而,其他一切都可以访问st[1]的所有成员。这只是当VFP代码试图访问is时。

事实上,在地址8003cedc、8003cee0和8003cee8,它们都在地址8003cfe4之前执行,可以愉快地访问该结构的成员。这让我相信这不是MMU访问问题?

这可能是缓存未命中的结果吗?或者是否有其他VFP问题试图在VFP系统和内存之间移动?或者是否存在协处理器尚未准备好的问题?

我能够通过删除所有浮点数学来避免这次崩溃。但这确实损害了应用程序的功能。我更希望浮点运算正确。

任何想法都将受到欢迎。

-Scotty

虽然我没有未知操作码的答案,但在第二部分的答案中,VFP协处理器必须在适当的边界上(在本例中为4个字节)将数据传输到它中。

虽然结构中的偏移正确对齐,但结构本身的底部却没有对齐。它在地址0x开始(由于打包)。。。2931。因此(+0x28)中40字节处的偏移位于奇数地址上。

只需添加

}  __attribute__ ((aligned (4)))

在结构的最后声明解决了问题。

***更新***

我尝试了许多方法在代码片段中复制这个问题。在所有情况下,编译器都会生成代码,在将32位值移动到neon处理器之前,将其从内存移动到寄存器。

我能够通过一个内联汇编语句强行导致数据故障,该语句试图将未对齐的数据直接从奇数地址移动到neon处理器。

asm("vstr  s15, [r0, #0x4] ");

(R0包含以x1结尾的基地址)

因此,这可能是GNU编译器中的一个优化错误。

如果其他人被这个问题咬了,我会发布这个。

由于我目前正在编写一个反汇编程序,我很快就抛出了问题的十六进制,得到了以下结果-没有保证或道歉!

EEF1FA10h,fmstat
DA000041h,ble #000083AC
EEFD7BE0h,ftosizd s15,d0
EDC47A0Ah,fsts s15,[r4+40]
E584702Ch,str r7, [r4+44]
E3A03000h,mov r3, 0
E5843030h,str r3, [r4+48]
EE07CA90h,fmsr s15,r12
EEF80BE7h,fsitod d0,s15
EE702BA2h,faddd d2,d0,d2
EEFD7BE2h,ftosizd s15,d2
EDC47A0Dh,fsts s15,[r4+52]
E5845018h,str r5, [r4+24]
EE701BA1h,faddd d1,d0,d1
EEFD7BE1h,ftosizd s15,d1

相关内容

  • 没有找到相关文章

最新更新