我尝试实现功能性 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.
}
}
如您所见,C++ 异常用于传输控制流。 也许可以有更帅气的设计?
问题:在功能性 ISA 模拟器上实现陷阱的最佳方法/实践是什么。我也对翻译模拟器(如 QEMU)的异常/陷阱实现感兴趣。
注意: trap 这个词是指 ISA 定义的陷阱,而不是应用程序错误:未对齐的内存访问、非法指令、系统寄存器访问错误、特权级别更改等.
最佳答案
QEMU 使用 C setjmp()/longjmp() 机制来处理大多数异常:当我们检测到页面错误之类的东西时,我们设置一些标志来指示异常类型,然后 longjmp() 到顶部 -级别“执行代码”循环。该循环然后查看标志并在继续执行客户代码之前将 CPU 状态设置为“进入异常处理程序”。
所以我们使用 C 等价物来抛出异常;正如 NonNumeric 所说,不需要像这样实现 guest 异常(名称的巧合只是巧合)。但是由于触发页面错误的内存访问是不常见的情况,longjmp 或抛出 C++ 异常比在所有内存访问代码路径中包含“处理失败返回”更有效。 guest 内存访问是一个特殊的热点,QEMU 使用一些自定义内联汇编实现其内存访问快速路径,因此我们关心在页面错误时退出到顶级循环而不执行 longjmp 所需的额外指令.使用简单的“获取/解码/执行”循环而不对 guest 代码执行 JIT 的模拟器不太关心性能,因此您的选择可能取决于代码风格和可维护性的偏好。
关于c++ - 在 C++ 的功能 ISA 模拟器上实现陷阱(异常/中断),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37388990/