The problem is that inside a C function I have an inline assembly. Something like
ldr r7, =0xdeadbeef
svc 0
If a literal pool wasn't created explicitly (this is the case), assembler creates one at the end of the translation unit. Usually this is fine, but if the translation unit turns out to be really huge, this doesn't work, because the literal pool is too far from the ldr instruction.
So, I wonder what is the best way to handle the problem. The most obvious way is to create a literal pool manually inside the 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 a suboptimal code because of the redundant branch instruction. I don't expect assembler to be clever enough to find an appropriate place for the constant pool inside the function. What I would like to do is to create a constant pool at the end of the function. Is there any way to tell the compiler (gcc) to create a literal pool at the end of the function?
PS I ended up using movw/movt
pair instead of constant pools. Though,
firstly, the movw/movt solution is slightly less portable than literal pools and,
secondly, I simply wonder if it is possible to use constant pools in inline assembly
both reliably and efficiently.
Update: So, what is the best way to handle the problem?
To force the toolchain to create a constant pool after the function one can put the function in a separate code section. It works because at the end of a translation unit assembler generates separate constant pools for each section.
Though, in fact, the best way is to avoid loading constants into registers in inline assembly at all. It's better to let the compiler do that. In my case I eventually wrote a code similar to
register int var asm("r7") = 0xdeadbeef;
asm volatile("svc 0\n" :: "r" (var));