如何告诉 GCC 在特定位置放置内联汇编指令?

How to tell GCC to place an inline assembly instruction at a specific position?

我正在为基于 ORPSoC 的处理器架构开发引导加载程序。为了执行一个程序,引导加载程序将其加载到内存中,然后跳转到该程序的开头。

现在我需要在跳转的延迟槽中插入自定义指令l.cust1。该指令由处理器执行并激活后续指令的解密。这就是为什么它 必须 放在延迟槽中的原因。再晚一点,程序就无法执行了,因为它的指令是加密的。同样,如果过早激活解密,bootloader会因为没有加密而崩溃。

我现在想知道是否可以告诉 GCC 在何处放置 l.cust1 指令。目前我必须相应地手动修改引导加载程序二进制文件。

在引导加载程序的 C 源代码中插入内联汇编 __asm__("l.cust1\n\t"); 会导致在相关跳转之前的某处添加指令:

1fc2e10:       9c 21 01 b4     l.addi r1,r1,436
1fc2e14:       70 00 00 00     l.cust1         # switching on decryption
1fc2e18:       18 40 01 ff     l.movhi r2,0x1ff
1fc2e1c:       9c 72 ff ff     l.addi r3,r18,-1
1fc2e20:       a8 42 7c 94     l.ori r2,r2,0x7c94
1fc2e24:       9c 90 00 04     l.addi r4,r16,4
1fc2e28:       85 62 00 60     l.lwz r11,96(r2)
1fc2e2c:       48 00 58 00     l.jalr r11
1fc2e30:       9d c0 00 00     l.addi r14,r0,0

但是,我需要它位于跳跃的延迟槽中:

1fc2e10:       9c 21 01 b4     l.addi r1,r1,436
1fc2e14:       9d c0 00 00     l.addi r14,r0,0
1fc2e18:       18 40 01 ff     l.movhi r2,0x1ff
1fc2e1c:       9c 72 ff ff     l.addi r3,r18,-1
1fc2e20:       a8 42 7c 94     l.ori r2,r2,0x7c94
1fc2e24:       9c 90 00 04     l.addi r4,r16,4
1fc2e28:       85 62 00 60     l.lwz r11,96(r2)
1fc2e2c:       48 00 58 00     l.jalr r11
1fc2e30:       70 00 00 00     l.cust1         # switching on decryption

您需要使用 asm volatile 和对您希望内联汇编继续进行的代码的人为依赖。示例取自 gcc documentation is below:

asm volatile ("mtfsf 255,%1" : "=X"(sum): "f"(fpenv));
sum = x + y;

根据文档 volatile 单独是不够的。换句话说,编译器仍然可能改变以下代码的顺序:

asm volatile("mtfsf 255,%0" : : "f" (fpenv));
sum = x + y;

通过添加依赖项,您可以确保内联程序集的放置。在第一个代码片段中,通过添加对 sum 的依赖,可以确保编译器不会对代码重新排序,因为它认为它会由于依赖而生成不同的结果。您可以在 "C code optimization" 部分的 this webpage 上找到另一个例子。

l.cust1 放在与跳转相同的内联汇编程序语句中,必须声明 volatile 因为它有副作用,并且在 clobber 列表中有 "memory" 因为它取决于关于记忆的内容。