The problem is that inside the C function, I have a built-in assembly. Sort of
ldr r7, =0xdeadbeef svc 0
If the literal pool was not created explicitly (this is so), the assembler creates one at the end of the translation unit. This is usually normal, but if the translation unit is really huge, it does not work because the Literal pool is too far from the ldr instruction.
So, I am wondering how best to deal with this problem. The most obvious way is to create a literal pool manually inside an inline assembly:
ldr r7, =0xdeadbeef svc 0 b 1f .ltorg 1:
or
ldr r7, 1f svc 0 b 2f 1: .word 0xdeadbeef 2:
Unfortunately, this leads to suboptimal code due to the excessive branch of the instruction. I do not expect the assembler to be smart enough to find a suitable place for a constant pool inside a function. What I would like to do is create a constant pool at the end of the function. Is there a way to tell the compiler (gcc) to create a literal pool at the end of a function?
PS In the end, I used the movw/movt pair instead of the constant pools. Although, firstly, the movw / movt solution is slightly less portable than literal pools, and secondly, I just wonder if it is possible to use persistent pools in the built-in assembly both reliably and efficiently.
Update: So, what is the best way to deal with the problem?
To force the toolchain to create a constant pool after the function, which you can put the function in a separate section of code. This works because at the end of the translation block, assembler creates separate constant pools for each section.
Although, in fact, the best way is to not load constants into registers in the built-in assembly at all. Better let the compiler do this. In my case, I eventually wrote code similar to
register int var asm("r7") = 0xdeadbeef; asm volatile("svc 0\n" :: "r" (var));