繁体   English   中英

Cortex-m4 asm vs cortex-m0 asm

[英]Cortex-m4 asm vs cortex-m0 asm

如何将 CM4 的这个汇编代码重写为 CM0? 这是来自 FreeRTOS 页面的硬故障处理示例。 它检查在硬故障发生之前哪个堆栈指针处于活动状态,并提供指向堆栈寄存器开头的指针:

" tst lr, #4                                                \n"
" ite eq                                                    \n"
" mrseq r0, msp                                             \n"
" mrsne r0, psp                                             \n"
" ldr r1, [r0, #24]                                         \n"
" ldr r2, handler2_address_const                            \n"
" bx r2                                                     \n"
" handler2_address_const: .word prvGetRegistersFromStack    \n"

如果没有任何更改,它会产生多个错误:

 Error: unshifted register required -- tst r0,#4''
 Error: selected processor does not support 'ite eq' in Thumb mode
 Error: Thumb does not support conditional execution
 Error: Thumb does not support conditional execution
 Error: invalid offset, target not word aligned (0x00000002)
 Error: invalid offset, value too big (0x00000002)

我尝试过的:

以这种方式替换tst并删除IT

" mov r1, lr\n"
" lsr r0, r1, #3\n"    // Replace tst with lsr and cmp
" cmp r0, #1\n"
" mrseq r0, msp\n"     // <- Error: Thumb does not support conditional execution
" mrsne r0, psp\n"     // <- Error: Thumb does not support conditional execution

好的。 启用称为统一语法的东西:

".syntax unified\n"
".thumb\n"
" mov r1, lr\n"
" lsrs r0, r1, #3\n"  // tst gives "Can not honor suffix width" so replaced it with lsrs and cmp
" cmp r0, #1\n"
" ite eq\n"          // <- Error: selected processor does not support `ite eq' in Thumb mode. If I remove it compiler states that mrseq must be in IT block
" mrseq r0, msp\n"
" mrsne r0, psp\n"
" ldr r1, [r0, #24]\n"
" ldr r2, handler2_address_const\n"
" bx r2\n"
" handler2_address_const: .word prvGetRegistersFromStack\n"

这些错误的原因是什么以及如何修复它们? 仍然不知道导致对齐问题的原因。

当然,CM0 不支持某些指令。 但我不明白错误“Thumb 不支持条件执行”以及如何在没有条件执行的情况下生存。

还有错误“不能接受寄存器宽度”是什么意思,以及为什么在启用统一语法时会发生这种情况。 据我了解,它是关于 16/32 位指令的。 尝试添加 .W 后缀,但出现另一个错误。

Cortex-M0 显然根本不支持预测; 没有条件执行。 显而易见的选择是分支。

您的 lsrs 序列看起来没有正确实现测试正确的位或测试单个位。 看起来这取决于所有更高的位为零。

GCC 输出https://godbolt.org/z/aphU5G展示了一种巧妙的方法,可以通过一个移位指令在单个位上进行分支: lsls r3, r0, #29 bpl .skip - 将位移至符号位,其中仅根据该位设置标志。 r3目标可以是任何可编码的虚拟寄存器; 你不在乎价值; 你只想要标志设置。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM