如今,仿真技术和虚拟技术被广泛应用各个领域,特别在嵌入式系统的开发过程中,由于在不同应用领域中,嵌入式开发要求的硬件体系差别很大,用软件进行系统仿真或虚拟硬件非常必要。软件仿真的重点是微控制器的仿真,而对微控制器的仿真重点又在指令仿真上,因此本文给出一种基于解释型仿真策略的指令仿真器的实现。指令集仿真器(Instruction Set Simulator,ISS)是用来在宿主机仿真另一种目标机上程序运行过程的软件工具。它通过仿真每条指令在目标处理器上的执行效果来仿真目标机程序,是目标处理器的软件仿真器。在嵌入式软硬件的并行开发中,指令仿真器是必不可少的工具之一,在目标机可用之前,通过它就可以完成软件的仿真调试,真正做到了软硬件的并行开发。
1 ARM体系架构及指令集模拟技术
1.1 ARM体系架构
到目前为止,ARM微处理器以其体积小、低功耗、低成本、高性能、指令执行速度快、寻址方式灵活简单、执行效率高、指令长度固定等优点几乎已经深入到各个领域。ARM处理器实现加载/存储(load/store)体系结构,是典型的RISC处理器。只有加载和存储指令可以访问存储器。数据处理指令支队寄存器的内容进行操作,传统的CISC(Complex Instruction Set Computer,复杂指令集计算机)技术的指令集随着计算机的发展引入了各种各样的复杂指令,已经不堪重负。图1描述了ARM微处理器的体系架构。
1.2 指令集模拟技术
1.2.1 指令集模拟解释型模拟技术
解释型模拟器的模拟流程是参照硬件环境中的指令执行,并不进行任何执行信息的服用,故执行起来性能不高,爱目前主流配置的主机上的运行性能能一般从几十到几百个KIPS(Kilo-Instructions Per-Second)。由于解释型模拟器实现较为简单,同时能够提供足够的模拟精度以及灵活性,但解释型模拟器的模拟性能低下,故在对于模拟性能没有特别高的要求下,采用这种模拟技术是非常优越的。目前绝大部分商用的模拟器是解释型模拟器。这类模拟器的典型代表是SimpleScalar。
1.2.2 指令集模拟器动态翻译模拟技术
动态翻译模拟是在解释型模拟技术基础上的一种优化,由于使用了缓存技术尽可能大的复用已解析的信息,提高了模拟的效率。模拟器的工作流程是:模拟一条指令,先核对这条指令是否存在于缓冲页,如果是,则调用存储中已有的解码结果,实现模拟;如果没有,则翻译该指令并将结果缓存页中备用,同时按照解释型模拟的模式,继续进行。由于启动模拟编译器的系统开销较大,为了提高性能,每次启动模拟编译器完成若干条指令的翻译,为了处理方便,每次编译的指令数是固定的,称为一个“翻译页”。在动态翻译模拟技术中,翻译和模拟的过程耦合度较低,可以分配给不同的线程完成,或结合多核技术,将代码的执行工作分配给几个CPU同时来执行,来提高模拟速度。目前采用动态翻译技术的应用的较好的模拟器有Intel IA-32 Execution Layer等。
2 ARM指令集模拟器的设计
2.1 ARM指令集模拟器系统总体框架设计
本模拟器的主要功能是模拟ARM处理器对指令集的处理能力,当把内容为ARM指令的二进制BIN文件输入时,可以模拟在真实ARM处理器上的运行效果。由图2指令集模拟器的总体架构图可以看出一个应用程序在运行的时候和指令集模拟器之间的关系。一个应用程序在经过ARM交叉编译器编译生成基于ARM指令集的二进制可执行文件,可执行文件进入ARM指令集模拟器内核被解释执行,最后得到运行后的结果。
其中模拟器内核是整个模拟器的核心部分,也是本文将要重点设计和实现的部分。它主要包含一下功能:对可执行文件的加载,执行取指令、指令译码、指令模拟执行的三级流水和解析结果的展示。在模拟器内核设计部分,模拟指令执行的过程是内核的核心部分,在本模拟器设计中,借鉴CPU模型中的指令流水设计内核翻译程序的取指、译码和指令执行3个过程。图3描述了指令集模拟器内核的总体架构。如图所示,整个内核包含程序加载模块、指令译码模块、取指模块、指令调度与模拟模块、寄存器模拟模块和数据存储模块。在此模拟器中,存储模块不做实现,调用gdb中的相应模块。
2.2 ARM指令集模拟器的流程设计
本模拟器是按照解释型模拟器的模拟策略设计的。解释型指令集模拟器基本上是以软件实现的虚拟机,它以解释的形式在宿主机上执行加载的目标代码,它的主体是一个具有3步过程的循环体,分别对应取指令、指令译码、指令执行3步操作。因此本ARM指令集模拟器的核心流程就是加载程序,之后进入读取指令、指令译码和指令执行的循环体中,当所有目标代码都执行之后结束并显示运行结果。整个流程如图4指令模拟器的工作流程所示。
2.3 ARM指令集模拟器的主要功能模块设计
2.3.1 指令译码模块
指令译码模块的功能就是根据ARM指令集编码,将要执行的二进制指令译码成操作码、操作数、条件码等指令模拟需要的信息。指令集模拟器的每一模拟步模拟一条指令的取指令、译码、执行等各个阶段,因此指令集模拟器中的指令译码与实际ARM处理器的译码并不是完全对应,同时也不会影响模拟的正确性。
在指令译码模块中,本文采用分类的思想,将指令集按照一定的规律进行分类解析,逐步解析,找到最终指令所对应的解析函数。这样做的目的是为了减少判断指令时的条件判断次数,采用分治的思想提高指令译码的效率。不过要想对指令译码效率有显著性的提高,还是要采用改进型的工作流程,主要原因是在指令译码的过程中,会出现大量的重复译码,所以改进型的工作流程中提出的指令缓存技术会很好的提高译码效率,减少重复的译码工作。
2.3.2 指令模拟与调度模块
指令模拟与调度功能模块是指令集模拟器的核心部分,也是实现代码量最大的部分,主要包括与虚拟指令集定义对应的一系列指令模拟函数、指令执行控制函数、指令翻译调度函数、中断处理函数以及一些公用函数。指令执行控制函数负责控制整个模拟过程,反汇编结果文件加载完毕后,程序就进入核心部分的模拟循环;指令翻译调度函数负责将目标指令转化为虚拟指令形式,然后指令模拟函数按照相应指令的功能定义完成指令的模拟,模拟结果是修改存储器、寄存器值:公用函数主要包括寻址方式判别、指令操作数分析、指令条件码判别、移位操作、ALU操作以及寄存器访问等。指令模拟与调度的循环过程如下:
1)取指令
该模拟器的输入是二进制可执行文件,因此取指令时,根据PC值取得的当前的指令,进行译码。
2)翻译
调用指令翻译函数获得虚拟指令。
3)调度
根据指令类型,调用相应的指令模拟函数。
4)执行
指令模拟函数对指令进行模拟。
5)中断检测与调度
为了对中断系统进行模拟,本文定义了对应于FIQ、IRQ的标志变量,可以改变他们来模拟外部中断输入,每条指令模拟结束后,必须检测上述两个标志,如果检测到中断发生,则调用相应的异常进入函数,PC被设定为中断服务程序入口地址。
6)更新PC值
如果本次循环没有发生指令跳转、加载PC及中断,PC顺序移向下一条指令。
2.4 ARM指令集模拟器的内核设计
模拟器内核结构如图5所示。
2.4.1 内核解码模块设计
指令模拟器内核中的解码模块包括取指令模型和指令转换模型两部分内容,取指令模型介绍了内核程序如何从加载的目标代码中取出逐条指令,指令转换模型介绍了取出的逐条指令是如何转换成中间语言指令来实现的。
1)取指令模型
本文设计的模拟器中取指令模型结构如图6所示,包括指令计数器、指令格式解析器、指令格式解析器、取指令逻辑控制器和指令地址更新逻辑。指令计数器是处理器都会有的一个寄存器。不同的处理器有不同的表现形式。
2)指令的转换模型
指令译码就是根据ARM指令集编码,将要执行的指令译成操作码、操作数、条件码等指令仿真需要的信息。译码的重点在于获取不同寻址方式下的操作数,通过分析指令字助记符和指令码,可以很方便地得到不同寻址方式的操作数。由于本文设计的指令集虚拟模拟ARM的指令集,所以加入指令转换模型,指令转换是将一条目标机器指令转换为一条或几条中间可执行指令集的过程。转换工作由指令转换器完成。其工作模型如图7所示,一条源指令经过指令译码模块翻译,生成一系列的中间语言队列,在本模拟器中,中间语言就是能在X86平台上运行的汇编语言。
2.4.2 内核指令模拟与调度模块
指令调度就是把指令字与完成相应操作的功能函数对应起来,使得仿真时取到该指令后能知道该调用哪个执行过程。本文是基于传统的解释型仿真策略,其主体是一个大的switch结构,并使用case语句。这种设计模型会影响模拟速度,由于case语句的种类非常多,所以在今后的工作中,这里将会是一个重点的研究对象,可以采用hash结构、压缩算法或者指令缓存来提高指令译码的执行效率,这也将会是模拟器的整体执行效率得到一个很大的提高。
指令模拟执行模块把指令分类处理并采用数据获取和数据操作相分离的方法,使得执行函数更具有通用性,当新的指令系统添加时,只需要添加相应的寻址方式和原系统中没有的指令执行过程,就能完成添加指令集的操作,提高了系统设计的可扩展性。
3 结束语
本文是针对嵌入式开发现阶段的主要存在的问题,即传统低下的开发效率和当下对较短市场开发周期的要求之间的矛盾,提出了ARM指令集模拟器的设计和实现方法。以及对指令集模拟技术的介绍和掌握。目前,与嵌入式系统相关的软件开发复杂度越来越高,因此指令集模拟器的发展前景十分乐观。