我已经编写了RISC样式处理器(以及所有外围设备)的完整系统模拟器/仿真器。目前,它使用间接线程仿真循环。即所有的指令页脚都是以下的风格:
pc += 4;
inst = loadWord(mem, pc);
instp = decodeTable[opcode(inst)];
goto *instp
性能相当不错,在启动Linux时,我在现代机器上获得了大约70-80 MIPS,这非常好。
但是,我正在考虑转向直接预编码的线程解释器模型,这看起来如下:
tPC += 1;
instp = predecodeMem[tPC].operation;
goto *instp;
预解码本身并不是一个问题,它只是替换现有的解码器和添加一些影子存储器。我的主要问题是自修改代码(或半自修改代码)。
在简单的情况下,我们可以在访问之前未执行的页面时懒惰地分配预编码页面。然后从所有条目中清除软件TLB以确保我们在下一次写入该页面时通过存储器模拟系统,因此,写入可执行页面将不得不更新解码信息以及性能成本,但是很少见,我们应该没有问题(我们也可以通过添加在运行时计算的子页面可执行位来加快速度)。
这里的问题是关于在仿真器内运行的操作系统重用页面时的长期代码发现。例如,内核页面可以由Linux内核分配,分配为一个进程的代码。下一次创建进程时,页面可能被分配为数据,但在刚刚描述的方案中,这会导致问题,因为现在纯数据页必须在每个字节写入时经历相当慢的预解码。
目前的一些想法,但我发现这些想法特别好,即它们都有明显的缺点:
我发现文献严重缺乏关于这一主题的讨论。有哪些常规方法可以在页面不再使用时对页面进行老化,以便我们例如清除与页面关联的执行位和预读码内存?