I am experiencing a HardFault exception in some code which computes a float expression with an integer operand. The operand is passed by address and it is then converted (either implicitly or with an explicit cast) to float. When the operand is not 32-bits aligned (which is not under my control), I get the exception.
I tried to reproduce the behavior on godbolt here and the generated code is consistent with what I get on my devices.
Basically, the following disassembly code
vldr.32 s0, [r0] @ int
directly uses the possibly unaligned address passed to the function in the vldr
instruction which requires aligned addresses.
I found this question which addresses a similar problem, but there they talk about float pointers. In that case I understand that floats can't be unaligned.
In my case I am dealing with integers, which are allowed to be unaligned and nonetheless the compiler assumes it can still use the address in the vldr instruction. What puzzles me even more is that this code
uint32_t pippo = *(uint32_t *)src;
float pippof = pippo * 10.0f;
may or may not generate the exception when provided with unaligned address, depending on the optimization level, because with -O0
for instance an integer is allocated on the stack.
So my questions are:
- is this correct behavior for the compiler (or the backend, maybe)? As the integers can be unaligned I would expect that the generated code passes from a CPU register.
- what is a correct strategy to avoid such an issue, when even passing through a temporary int variable is not safe?