我想使用模拟器在现有架构(x86)上测试一些架构更改。然而,为了正确测试它们并运行基准测试,我可能必须对指令集进行一些更改,有没有办法将这些更改添加到 GCC 或任何其他编译器?
一种常见的方法是添加内联汇编,并直接对指令字节进行编码。
例如:
int main()
{
asm __volatile__ (".byte 0x90\n");
return 0;
}
编译(gcc -O3)为:
00000000004005a0 <main>:
4005a0: 90 nop
4005a1: 31 c0 xor %eax,%eax
4005a3: c3 retq
因此只需将 0x90 替换为您的 inst 字节即可。当然,您不会在常规 objdump 上看到实际指令,并且该程序可能不会在您的系统上运行(除非您使用 nop 组合之一),但如果在那里正确实现,模拟器应该能够识别它。
请注意,当编译器不知道这条指令时,您不能指望编译器能够很好地为您优化,并且如果它更改状态(寄存器,内存),您应该小心并使用内联汇编破坏/输入/输出选项,以确保正确性。仅在必要时才使用优化。
另一种方法是在编译器中实现这一点 - 它可以在 gcc 中完成,但正如评论中所述,LLVM 可能是最好用的方法之一,因为它被设计为编译器开发平台,但它仍然非常有用复杂,因为 LLVM 最适合 IR 优化阶段,并且在尝试修改特定于目标的后端时不太友好。
尽管如此,它仍然是可行的,如果您还计划让编译器决定何时发出此指令,则必须这样做。 我建议从第一个选项开始,看看你的模拟器是否可以使用这个添加,然后才花时间在编译器方面。
如果您决定在 LLVM 中实现此功能,最好的选择是将其定义为内部函数,这里有相对更多的相关文档 - http://llvm.org/docs/ExtendingLLVM.html
您可以添加新指令,或通过修改 GCC 中称为“机器描述”的文件组来更改现有指令。
<target>.md
文件中的指令模式,<target>.c
文件中的一些代码,谓词,约束等。所有这些都位于 $GCCHOME/gcc/config/<target>/
文件夹中。所有这些东西都使用从 RTL 生成 ASM 代码的步骤。您还可以通过更改其他一些通用 GCC 源文件、更改 SSA 树生成、RTL 生成来更改发出指令的情况,但所有这些都有点复杂。
简单解释一下发生了什么:
https://www.cse.iitb.ac.in/grc/slides/cgotut-gcc/topic5-md-intro.pdf
这是可行的,我已经做到了,但是很乏味。它基本上是使用现有平台作为模型将编译器移植到新平台的过程。 GCC 中的某个位置有一个定义指令集的文件,它在编译过程中经历各种过程,生成进一步的代码和数据。距我这样做已有 20 多年了,所以我忘记了所有细节,抱歉。