How would one rewrite this assembly code for CM4 to CM0? This is example of hardfault handling from FreeRTOS page. It checks which stack pointer was active before hardfault occurred and gives pointer to the beginning of stacked registers:
" 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"
Without any changes it produces multiple errors:
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)
What I have tried:
Replace tst
and remove IT
this way
" 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
Ok. Enable something called unified syntax:
".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"
What are the reasons for those errors and how to fix them? Still got no idea what causes alignment problem.
Certainly some instruction are not supported on CM0. But I don't understand error "Thumb does not support conditional execution" and how to live without conditional execution.
Also what does error "Can not honor register width" means and why it occurs when unified syntax is enabled. As I understand it is something about 16/32 bit instructions. Tried to add .W suffix but got another error.
Cortex-M0 apparently doesn't support predication at all; no conditional execution. The obvious option would be to branch.
Your lsrs sequence doesn't look like it correctly implements testing the right bit, or testing a single bit. Looks like it depends on all higher bits being zero.
GCC output https://godbolt.org/z/aphU5G shows a clever way to branch on a single bit with one shift instruction: lsls r3, r0, #29
; bpl .skip
- shifts the bit to the sign bit where a flag is set based on just that bit. The r3
destination can be any dummy register that's encodeable; you don't care about the value; you just want the flag setting.
User contributions licensed under CC BY-SA 3.0