我想使用模拟器在已经存在的架构(x86)上测试一些架构更改。但是,为了正确测试它们并运行基准测试,我可能必须对指令集进行一些更改,有没有办法将这些更改添加到 GCC 或任何其他编译器?
3 回答
简单的解决方案:
一种常见的方法是添加内联汇编,并直接对指令字节进行编码。
例如:
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
所以只需用你的 inst 字节替换 0x90 。当然,您不会在常规 objdump 上看到实际指令,并且该程序可能不会在您的系统上运行(除非您使用 nop 组合之一),但如果在那里正确实施,模拟器应该会识别它。
请注意,当编译器不知道此指令时,您不能期望编译器为您优化,如果它改变状态(寄存器、内存),您应该小心并使用内联汇编 clobber/输入/输出选项,以确保正确性。仅在必要时使用优化。
复杂的解决方案
另一种方法是在你的编译器中实现它 - 它可以在 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 多年了,所以我忘记了所有细节,对不起。