What is the correct way to create a persistent pool for an inline assembly?

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)); 
+5
source share
1 answer

You can use -ffunction-sections and, as requested by -ffunction-section , use ld --gc-sections to remove unused code.

There is an obvious file split.

The solution that should work is to use the naked function with the unused annotation, since it is never called. Put one .ltorg here, and put both functions in a special section; .text.ltorg_kludge , for example. The script compiler must use .text* , and functions in the same subsections are placed together. In some ways, this is similar to file splitting, as the compiler will try to static functions.

You can rely on the compiler emission functions that occur in the source without a special section. However, I'm not sure if this is a standard or random position. Compilers can optimize better by issuing a function in some ordering of the DAG call hierarchy.


In addition: movw / movt more efficient due to cache effects. It also works with ARMv6 and on Thumb2 code. I don’t see portability as a big deal (since the built-in assembler isn’t portable, and you probably prefer performance over portability), but the issue is related to ARMv4 / 5 users.


I explored the use of the R constraint from the gcc machine constraint ,

R
Constant pool item

However, a sample with gcc-4.8 gives an error an impossible restriction. Using alternative letters, such as C , also gives the same error message. Checking the source of contraints.md seems to indicate that the R constraint is just documentation. Unfortunately, as it sounds specifically to solve this problem.

The compiler may be loading this value, but it may not be optimal depending on the inline assembler. For instance,

  asm(" add %0, %0, %1\n" : "+r" (0xdeadbeef) : "r" (0xbaddeed0)); 
+3
source

Source: https://habr.com/ru/post/1214561/


All Articles