为内联汇编创建常量池的正确方法是什么?

问题是在C函数内部我有一个内联汇编。 就像是

ldr r7, =0xdeadbeef svc 0 

如果未明确创建文字池(这是这种情况),汇编程序会在翻译单元的末尾创建一个文字池。 通常这很好,但是如果翻译单元真的很大,那么这不起作用,因为文字池离ldr指令太远了。

所以,我想知道处理这个问题的最佳方法是什么。 最明显的方法是在内联汇编中手动创建文字池:

  ldr r7, =0xdeadbeef svc 0 b 1f .ltorg 1: 

要么

  ldr r7, 1f svc 0 b 2f 1: .word 0xdeadbeef 2: 

不幸的是,由于冗余分支指令,这导致了次优代码。 我不希望汇编器足够聪明,为函数内部的常量池找到合适的位置。 我想要做的是在函数的末尾创建一个常量池。 有没有办法告诉编译器(gcc)在函数末尾创建一个文字池?

PS我最终使用了movw/movt对而不是常量池。 虽然,首先,movw / movt解决方案的可移植性略低于文字池,其次,我只是想知道是否可以可靠而有效地在内联汇编中使用常量池。


更新: 那么,处理问题的最佳方法是什么?

要强制工具链在函数之后创建常量池,可以将函数放在单独的代码部分中。 它的工作原理是因为在翻译单元结束时汇编程序为每个部分生成单独的常量池。

实际上, 最好的方法是避免将常量加载到内联汇编中的寄存器中。 让编译器这样做会更好。 在我的情况下,我最终写了一个类似的代码

 register int var asm("r7") = 0xdeadbeef; asm volatile("svc 0\n" :: "r" (var)); 

您可以使用-ffunction-sections并根据-ffunction-section上的查询 ,使用ld --gc-sections来删除未使用的代码。

有明显的分裂文件。

应该使用的解决方案是使用带有unused注释的naked函数,因为它从未被调用过。 在这里放置一个.ltorg ,并将两个函数放在一个特殊的部分; 例如.text.ltorg_kludge 。 链接描述文件应使用.text*并将相同子部分中的函数放在一起。 在某些方面,这就像拆分文件一样,因为编译器会尝试内联static函数。

您可以依赖源代码中遇到的编译器发射函数,而不需要特殊的部分。 但是,我不确定这是标准还是发生的立场。 编译器可以通过在调用层次结构的某些DAG排序中发出函数来更好地优化。


另外:由于缓存效应, movw / movt更有效。 它也适用于ARMv6及以上的Thumb2代码。 我不认为可移植性是一个大问题(因为内联汇编程序是不可移植的,你可能更喜欢性能而不是可移植性 ),但这个问题与ARMv4 / 5用户有关。


我研究了从gcc机器约束中使用R 约束 ,

[R
常量池中的项目

但是, 使用gcc-4.8的样本会给出错误不可能的约束 。 使用像C这样的替代字母也会给出相同的错误消息。 检查源contraints.md似乎表明R约束是仅文档function。 不幸的是,因为它听起来是为解决这个问题而建的。

编译器可以加载该值,但这可能是次优的,具体取决于inline汇编程序。 例如,

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