在C++的功能ISA模拟器上实现陷阱(异常/ intterupts)

Jet*_*ura 4 c++ qemu mips emulation riscv

我尝试实现功能ISA模拟器:目标是RISC-V和MIPS.这是一步一步的指令翻译.

抽象步骤:

while(num_steps)
{
    try
    {
        take_interrupt();// take pending interrupts
        fetch(); // fetch instruction from memory
        decode(); // find handler to instruction
        execute(); // perform instruction
    } 
    catch (Trap& e)
    {
        take_trap(e); //configure appropriate system registers and jump to trap vector.
    }
}
Run Code Online (Sandbox Code Playgroud)

如您所见,C++异常用于传输控制流.也许有更帅气的设计?

问题:在功能性ISA模拟器上实现陷阱的最佳方法/实践是什么.我也对翻译模拟器的异常/陷阱实现感兴趣,比如QEMU.

注意:通过单词trap我的意思是ISA定义的陷阱,而不是应用程序错误:未对齐的内存访问,非法指令,系统寄存器访问错误,权限级别更改等.

Pet*_*ell 5

QEMU使用C setjmp()/ longjmp()机制来处理大多数异常:当我们检测到类似页面错误的东西时,我们设置一些标志来指示异常的类型,然后将longjmp()放到顶层"执行"代码"循环.然后该循环查看标志并在继续执行访客代码之前为"输入异常处理程序"设置CPU状态.

所以我们使用相当于抛出异常的C; 正如NonNumeric所说,没有要求像这样实现客户端异常(名称巧合只是巧合).但由于触发页面错误的内存访问是非常见的情况,因此longjmp或抛出C++异常更有效,而不是在所有内存访问代码路径中包含"handle failure return".访客内存访问是一个特定的热点,QEMU通过一些自定义内联汇编实现其内存访问快速路径,因此我们关心在没有执行longjmp的情况下退出到页面错误的顶级循环所需的额外少数指令.使用简单的"获取/解码/执行"循环而不执行客户代码JIT的模拟器并不关心性能,因此您的选择可能归结为代码样式和可维护性的首选项.