在C++的功能性ISA模拟器上实现陷阱(异常/中断)
Implementation of traps(exceptions/intterupts) at functional ISA simulator at C++
我尝试实现功能性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(。然后,该循环查看标志,并在继续执行来宾代码之前为"输入异常处理程序"设置CPU状态。
因此,我们使用C等价于抛出异常;正如NonNumeric所说,不需要实现这样的来宾异常(名称的巧合只是巧合)。但是,由于触发页面错误的内存访问是不常见的情况,因此长jmp或抛出C++异常比在所有内存访问代码路径中包含"处理失败返回"更有效。来宾内存访问是一个特殊的热点,QEMU通过一点自定义的内联程序集实现了其内存访问快速路径,因此我们关心在不执行longjmp的情况下退出到页面错误的顶层循环所需的额外少量指令。一个模拟器使用一个简单的"获取/解码/执行"循环,而不执行来宾代码的JIT,它不太关心性能,所以你的选择可能取决于对代码风格和可维护性的偏好。
QEMU是用C编写的,所以它不使用C++异常。您也不必通过C++异常来处理ISA陷阱。异常应该在对您作为实现者有用时使用,仅此而已。
还要注意,陷阱并不是特别的东西,它们仍然是模拟系统工作流程的一部分。像这样编码除法是完全合法的
if (reg[divisor] != 0)
reg[target] = reg[divident] / reg[divisor];
else
trap(TRAP_DIV0)
其中trap()
函数直接更新架构状态,以便下一个要模拟的指令将来自异常处理程序。
void trap(int trap_id)
{
// save relevant registers according to platform spec
...
// set instruction pointer to trap handler start
reg[IP_INDEX] = trap_table[trap_id].ip;
// update other registers according to spec
...
}
C++异常可以让你的生活更轻松。例如,许多平台上的内存访问需要将虚拟地址转换为物理地址。此转换可能会导致陷阱(由于访问权限不足或配置错误)。写起来可能更容易:
void some_isa_instruction_handler()
{
int value1 = read_memory(address1);
int value2 = read_memory(address2);
int res = perform_something(value1, value2);
write_memory(address3, res);
}
当需要ISA陷阱时,CCD_ 2和CCD_。然后,take_trap()
函数将回滚中断的指令处理程序执行的任何更改(如果需要),并设置执行以模仿陷阱处理程序,就像上面的trap()
所做的那样。
模拟CISC系统可能会从这种风格中受益更多。
- 处理多个异常集合的C++方法
- 我在c++代码中生成了一个运行时#3异常
- 孤立代码块在结构中引发异常
- C++中的赋值发生,尽管右侧出现异常
- 从构造函数抛出异常时如何克服内存泄漏
- 异常属于C++中的线程还是进程
- 当类定义不可见时捕获异常
- 引发异常:读取访问冲突**dynamicArray**为0x1118235.发生
- 为什么异常不退出程序?
- 为什么我应该在异常处理中使用std::cerr而不是std::cout
- 如何修复链表类实现的未处理异常0xDDDDDDDD
- 关于:C++中异常对象的范围:为什么我没有得到副本?
- 是什么导致了Unity 3D中的"错误线程异常"?
- 如何将strftime中的格式错误作为异常捕获
- 创建具有 new in 函数和"this is nullptr"异常的对象
- 尝试使用智能指针时引发异常
- 函数如何通知用户它基于函数原型抛出异常?
- 是否值得降低我的代码的可读性,以便在出现内存不足错误时提供异常安全性?
- 当我使用 C++ 中的 C# dll 来使用 Selenium 时,存在异常处理问题
- 在C++的功能性ISA模拟器上实现陷阱(异常/中断)