Three broad solutions to the problem of architecture-specific program execution exist. These are static recompilation, dynamic recompilation, and interpretive emulation. In each case, an emulation program is written, usually on the alternative or host architecture, that translates a sequence of source program instructions intended for the source or emulated architecture into one or more instructions in the host's instruction language that perform the same function. The emulation program can be written to simulate the actions of each source program instruction individually, or to simulate the actions of several source program instructions in a single step. In general, simulation of each source program instruction individually provides greater emulation accuracy at the expense of execution speed.
针对那些体系结构相关的的可执行程序,存在着三种主流的解决方案:static recompilation, dynamic recompilation and interpretive emulation. 对于每一种方案来说,一个在仿真器上跑的程序通常是把针对源或者被仿真架构的源程序指令序列翻译成相同的功能的一条或多条host的指令语言。这个仿真程序可以有几种实现方法:
针对那些体系结构相关的的可执行程序,存在着三种主流的解决方案:static recompilation, dynamic recompilation and interpretive emulation. 对于每一种方案来说,一个在仿真器上跑的程序通常是把针对源或者被仿真架构的源程序指令序列翻译成相同的功能的一条或多条host的指令语言。这个仿真程序可以有几种实现方法:
- 针对每一条源程序指令的模拟;
- 用一个单步执行来模拟几个源程序指令;
一般来说,在牺牲速度的情况下,前者提供了很好的仿真精度。
In static recompilation, the emulated program is swept through in its entirety prior to execution and translated to a host program. The host program is then executed. This is rarely a complete solution since most programs exhibit dynamic behavior that cannot be predicted statically. For example, a branch instruction may depend upon a result computed by previous instructions that cannot be predicted prior to running the program. Therefore, the branch instruction cannot be translated to its meaningful counterparts in the host's language. Static recompilation also suffers from the shortcoming of requiring significant amounts of memory to store the translated copy of the program. In addition, static recompilation requires a complete understanding of the behavior of all possible programs. Thus, static recompilation is not a complete solution to effectively translating computer programs for emulation.
对于static recompilation来说,仿真程序会在被执行和翻译成host程序之前扫一遍,然后才是host程序的执行。这是一个少有的、完整的方案因为许多程序有动态的特性,也就意味着不能被静态的过一遍。比如,一个转移指令可能依赖于一个动态的、无法提前预知的计算结果。这种方式也需要巨大的memory来支持。此外,它也要求完全理解程序可能的行为。所以对于为仿真器有效的翻译计算机程序来说它不是一种通解。
Dynamic recompilation allows emulation of programs that exhibit dynamic behavior such as branch instructions. In dynamic recompilation, programs are statically translated until a problem instruction (usually a branch) that cannot be accurately translated is reached. The translated program is then executed up to this point such that the architectural state of the emulated machine is updated. The problem instruction can then be emulated by the execution of an emulation routine corresponding to the problem instruction, after which static translation can begin again. This method can successfully emulate any program and is efficient if large sections of source instructions can be statically translated. However, the translator must run concurrently with the emulated program, and adds significant overhead to the emulation process. The speed and memory requirements are difficult to predict, and will vary greatly depending upon the character of the emulated program.
Dynamic recompilation allows emulation of programs that exhibit dynamic behavior such as branch instructions. In dynamic recompilation, programs are statically translated until a problem instruction (usually a branch) that cannot be accurately translated is reached. The translated program is then executed up to this point such that the architectural state of the emulated machine is updated. The problem instruction can then be emulated by the execution of an emulation routine corresponding to the problem instruction, after which static translation can begin again. This method can successfully emulate any program and is efficient if large sections of source instructions can be statically translated. However, the translator must run concurrently with the emulated program, and adds significant overhead to the emulation process. The speed and memory requirements are difficult to predict, and will vary greatly depending upon the character of the emulated program.
相对于static recompilation来说,dynamic recompilation允许程序仿真器具备动态特性,比如转移指令。对于dynamic recompilation来说,程序被静态的翻译直到遇到了一个有疑问的指令(它不能准确的翻译) - 比如转移指令。然后翻译程序会执行有疑问指令之前的指令,这样这条疑问指令就不再成为疑问指令了,接着,翻译程序继续自己的静态翻译...
对于dynamic recompilation方式,仿真程序会因为其特性(比如含有转移指令的多少等)被翻译的程序反复执行,也就是说其速度和memory要求是因程序而异的。
Interpretive emulation emulates each source instruction as a separate entity. Interpretive emulation provides an architecturally distinct state at each emulated source instruction boundary, and has the potential of being the most accurate and interactive of the three emulation techniques. Interpretive emulation typically has a predictable and potentially small memory requirement, since no translated copy of the program need be stored. However, interpretive emulation can be the slowest method, requiring many more host instructions to emulate a given source instruction as compared to either static or dynamic recompilation.
Interpretive emulation仿真每一条源指令并将其作为一个单独的实体。它的memory需求是最少的,以为它不需要存储被翻译程序的copy...
Interpretive emulation emulates each source instruction as a separate entity. Interpretive emulation provides an architecturally distinct state at each emulated source instruction boundary, and has the potential of being the most accurate and interactive of the three emulation techniques. Interpretive emulation typically has a predictable and potentially small memory requirement, since no translated copy of the program need be stored. However, interpretive emulation can be the slowest method, requiring many more host instructions to emulate a given source instruction as compared to either static or dynamic recompilation.
Interpretive emulation仿真每一条源指令并将其作为一个单独的实体。它的memory需求是最少的,以为它不需要存储被翻译程序的copy...
An emulator reads emulated code from memory byte-by-byte, decodes it, and performs appropriate commands on the emulated registers, memory, and I/O. The general algorithm for such emulator is following:
while(CPUIsRunning)
{
Fetch OpCode
Interpret OpCode
}
Virtues of this model include ease of debugging, portability, and ease of synchronization (you can simply count clock cycles passed and tie the rest of your emulation to this cycle count). A single, big, and obvious weakness is the low perfomance. The interpretation takes a lot of CPU time and you may require a pretty fast computer to run your code at a decent speed.
{
Fetch OpCode
Interpret OpCode
}
Virtues of this model include ease of debugging, portability, and ease of synchronization (you can simply count clock cycles passed and tie the rest of your emulation to this cycle count). A single, big, and obvious weakness is the low perfomance. The interpretation takes a lot of CPU time and you may require a pretty fast computer to run your code at a decent speed.