jpcsp源码解读8:cpu状态
2012-03-22 16:13
232 查看
从通用寄存器开始说起。
通用寄存器用一个类public class GprState来表示,其中的成员变量只有一个:
public final int[] gpr = new int[32];
也就是用32个整形数模拟32个32位通用寄存器。
这个类提供了操作这些寄存器的接口,例子如:
public void reset()
把32个寄存器都复位清零
public final void doSLL(int rd, int rt, int sa)
把rt号寄存器中的数据左移sa位,结果存放到rd号寄存器中
其余的还有:两个寄存器rs,rt的内容相加,结果存放到寄存器rd中 等等这样的方法,这里不一一列出,看源码就很清楚。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
注意,这里只是提供了操作寄存器的方法,而不是具体的指令。指令由另外的类来描述,他们的联系在于,每个指令的实现动作会调用特定的操作寄存器的方法。关于指令类的内容,将在下一篇日志中详解。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
现在,我们只有关于32个通用寄存器的描述,但是这还不足以描述一个完整的处理器。
在mips架构中,为乘法和除法另外定义了两个寄存器,hi和lo。两个32位数相乘,结果应该是64位。hi就是high的意思,是64位结果的高32位。lo就是low的意思,64位结果的低32位。在除法的情形,则分别用来存放商(lo)和余数(hi)。
在jpcsp中采取的手法是,将乘除法单元定义为前述通用寄存器类GprState的子类。这样,这个子类就继承了父类的所有成员变量和方法。也就是说,子类的实例可以引用父类中的所有方法,子类实例中包含了父类中定义的所有成员变量。
乘除法单元类:
public class MduState extends GprState
mdu的意思就是Multiply Divide Unit
这个子类中另外加入的成员变量只有一个(再次提醒,他已经继承了父类中的32个通用寄存器):
public long hilo;
也就是将两个32位寄存器打包在一个long型变量中。在这个类中定义了操作hilo寄存器的接口,如 乘法,除法,乘加 等。还有mfhi,mflo这样的方法。同样的,这些只是操作寄存器的方法,而不是指令。指令类的具体实例会调用这些方法。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
用同样的手法,定义MduState的子类,把访存单元包含进来:
public class LsuState extends MduState
看一下其中引入的成员变量:
public static final Memory memory = Memory.getInstance();
protected static final boolean CHECK_ALIGNMENT = true;
看到了内存类Memory,很好很强大。也就是说,cpu状态中把内存状态也包含进来了。
这个类提供的方法在这里列出两个:
public void doLB(int rt, int rs, int simm16)
public void doSH(int rt, int rs, int simm16)
(LB就是load byte,SH就是store half)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
继续定义LsuState的子类,这次加入的是分支控制单元(Branch Control Unit):
public class BcuState extends LsuState
新加入的成员变量:
public int pc;
public int npc;
也就是当前的pc(program counter)值,以及当前指令的下一条指令地址。
提供了一些关于分支动作的接口:
public boolean doJR
public boolean doBLTZ
public void nextPc
jr表示jump register;bltz表示branch on less than zero;nextPC就是没有分支,顺序推进pc值。
等
这些动作会更改pc值。还提供了两个方法,根据当前pc值从内存中取指令:
public int fetchOpcode()
public int nextOpcode()
现在,我们有了通用寄存器,hilo,内存,pc和npc,还有取指方法,还有更改各个寄存器的方法,处理器的状态机已经构建起来。
因为mips架构下,I/O操作和内存访问采用统一编址,所以有理由相信,I/O操作被封装进了Memory类中。也可能因为系统调用被包含进了虚拟机,导致根本不需要牵涉I/O操作的访存指令。这些都是此刻的臆想和猜测,分析Memory类的源码之后就会明晰。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
现在,将浮点单元加入进来:
public class FpuState extends BcuState
成员变量:
public static final class Fcr0
public float[] fpr;
public Fcr31 fcr31;
其中fpr和fcr31在构建函数中的初始化:
fpr = new float[32];
fcr31 = new Fcr31();
fpr是32个32位浮点寄存器。fcr31和fcr0是控制寄存器。
fcr0中我们这里只实现两个字段:
浮点单元实现编号imp = 0
浮点指令集版本号rev = 0
fcr31中实现3个字段:
rm,双精度浮点数据类型是否实现
c,浮点条件码;记录浮点比较结果,用于条件跳转或转移
fs,冲刷到0;这位设置时,非正常运算的结果将被设为0,而不是产生一个例外
这个类提供了浮点操作和控制接口,如浮点运算,读取或配置浮点控制寄存器等,具体见源码,不在此处列出。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
加入向量单元:
public class VfpuState extends FpuState
具体成员变量,寄存器,操作等内容,比较庞杂,暂且不去研究这个问题,以后再补上。现在先着力于摸清模拟器架构,所以对于已经知道的东西,就顺带附上些细节。对于庞杂的没研究过的枝叶,先放一边。
也可以参考这个网页:http://hitmen.c02.at/files/yapspd/psp_doc/chap4.html#sec4.5.1也就是其中的4.5.1章节。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
关于hitmen
http://hitmen.c02.at/files/yapspd/psp_doc/
这个网站提供了详尽的关于psp的硬件信息,作者声称其中内容全部出自猜测。应该是破解人员艰苦工作的成果,在此向他们致敬,呵呵。这个网站中的内容,如其标题所述,是psp硬件的英文文档。而我在写的东西,旨在阐明硬件和模拟器源码的对应关系,也就是说明模拟器的架构和设计方法。希望这会对一些人产生意义。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
回到正题,再继承一次VfpuState,就得到了一个完整的处理器类:
public class CpuState extends VfpuState
其中没有增加任何东西,只是一次外层包装,换个名字,在逻辑上更加清晰和一致。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
现在来看这个cpu状态类,其中包括了 通用寄存器,乘除法单元,访存单元(含内存),分支控制单元,浮点单元,向量单元;并且包含对这些单元的操作方法。
只要外面再加一层封装,初始化某一块只读的内存单元,其中装载固件,然后操作这个cpu,取指令,解析指令并调用这个cpu状态类的相应方法,虚拟机就运行起来了。
对于I/O,可以在访存单元中判定访存地址,来确定实际操作的硬件单元,然后将这些操作映射到我们虚拟的硬件设备上(比如用一个画布类虚拟出来的游戏机屏幕)。
另一种可选方案是,截获用户的所有系统调用,并且在虚拟机中完成这些系统调用请求的功能(硬件I/O,内存管理等)(而不是在虚拟机上运行的固件中完成)。
对于中断,可以作为一个事件传递给cpu实例,要求其作出适当响应。
指令的异常可以作为exception给throw出去。
通用寄存器用一个类public class GprState来表示,其中的成员变量只有一个:
public final int[] gpr = new int[32];
也就是用32个整形数模拟32个32位通用寄存器。
这个类提供了操作这些寄存器的接口,例子如:
public void reset()
把32个寄存器都复位清零
public final void doSLL(int rd, int rt, int sa)
把rt号寄存器中的数据左移sa位,结果存放到rd号寄存器中
其余的还有:两个寄存器rs,rt的内容相加,结果存放到寄存器rd中 等等这样的方法,这里不一一列出,看源码就很清楚。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
注意,这里只是提供了操作寄存器的方法,而不是具体的指令。指令由另外的类来描述,他们的联系在于,每个指令的实现动作会调用特定的操作寄存器的方法。关于指令类的内容,将在下一篇日志中详解。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
现在,我们只有关于32个通用寄存器的描述,但是这还不足以描述一个完整的处理器。
在mips架构中,为乘法和除法另外定义了两个寄存器,hi和lo。两个32位数相乘,结果应该是64位。hi就是high的意思,是64位结果的高32位。lo就是low的意思,64位结果的低32位。在除法的情形,则分别用来存放商(lo)和余数(hi)。
在jpcsp中采取的手法是,将乘除法单元定义为前述通用寄存器类GprState的子类。这样,这个子类就继承了父类的所有成员变量和方法。也就是说,子类的实例可以引用父类中的所有方法,子类实例中包含了父类中定义的所有成员变量。
乘除法单元类:
public class MduState extends GprState
mdu的意思就是Multiply Divide Unit
这个子类中另外加入的成员变量只有一个(再次提醒,他已经继承了父类中的32个通用寄存器):
public long hilo;
也就是将两个32位寄存器打包在一个long型变量中。在这个类中定义了操作hilo寄存器的接口,如 乘法,除法,乘加 等。还有mfhi,mflo这样的方法。同样的,这些只是操作寄存器的方法,而不是指令。指令类的具体实例会调用这些方法。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
用同样的手法,定义MduState的子类,把访存单元包含进来:
public class LsuState extends MduState
看一下其中引入的成员变量:
public static final Memory memory = Memory.getInstance();
protected static final boolean CHECK_ALIGNMENT = true;
看到了内存类Memory,很好很强大。也就是说,cpu状态中把内存状态也包含进来了。
这个类提供的方法在这里列出两个:
public void doLB(int rt, int rs, int simm16)
public void doSH(int rt, int rs, int simm16)
(LB就是load byte,SH就是store half)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
继续定义LsuState的子类,这次加入的是分支控制单元(Branch Control Unit):
public class BcuState extends LsuState
新加入的成员变量:
public int pc;
public int npc;
也就是当前的pc(program counter)值,以及当前指令的下一条指令地址。
提供了一些关于分支动作的接口:
public boolean doJR
public boolean doBLTZ
public void nextPc
jr表示jump register;bltz表示branch on less than zero;nextPC就是没有分支,顺序推进pc值。
等
这些动作会更改pc值。还提供了两个方法,根据当前pc值从内存中取指令:
public int fetchOpcode()
public int nextOpcode()
现在,我们有了通用寄存器,hilo,内存,pc和npc,还有取指方法,还有更改各个寄存器的方法,处理器的状态机已经构建起来。
因为mips架构下,I/O操作和内存访问采用统一编址,所以有理由相信,I/O操作被封装进了Memory类中。也可能因为系统调用被包含进了虚拟机,导致根本不需要牵涉I/O操作的访存指令。这些都是此刻的臆想和猜测,分析Memory类的源码之后就会明晰。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
现在,将浮点单元加入进来:
public class FpuState extends BcuState
成员变量:
public static final class Fcr0
public float[] fpr;
public Fcr31 fcr31;
其中fpr和fcr31在构建函数中的初始化:
fpr = new float[32];
fcr31 = new Fcr31();
fpr是32个32位浮点寄存器。fcr31和fcr0是控制寄存器。
fcr0中我们这里只实现两个字段:
浮点单元实现编号imp = 0
浮点指令集版本号rev = 0
fcr31中实现3个字段:
rm,双精度浮点数据类型是否实现
c,浮点条件码;记录浮点比较结果,用于条件跳转或转移
fs,冲刷到0;这位设置时,非正常运算的结果将被设为0,而不是产生一个例外
这个类提供了浮点操作和控制接口,如浮点运算,读取或配置浮点控制寄存器等,具体见源码,不在此处列出。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
加入向量单元:
public class VfpuState extends FpuState
具体成员变量,寄存器,操作等内容,比较庞杂,暂且不去研究这个问题,以后再补上。现在先着力于摸清模拟器架构,所以对于已经知道的东西,就顺带附上些细节。对于庞杂的没研究过的枝叶,先放一边。
也可以参考这个网页:http://hitmen.c02.at/files/yapspd/psp_doc/chap4.html#sec4.5.1也就是其中的4.5.1章节。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
关于hitmen
http://hitmen.c02.at/files/yapspd/psp_doc/
这个网站提供了详尽的关于psp的硬件信息,作者声称其中内容全部出自猜测。应该是破解人员艰苦工作的成果,在此向他们致敬,呵呵。这个网站中的内容,如其标题所述,是psp硬件的英文文档。而我在写的东西,旨在阐明硬件和模拟器源码的对应关系,也就是说明模拟器的架构和设计方法。希望这会对一些人产生意义。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
回到正题,再继承一次VfpuState,就得到了一个完整的处理器类:
public class CpuState extends VfpuState
其中没有增加任何东西,只是一次外层包装,换个名字,在逻辑上更加清晰和一致。
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
现在来看这个cpu状态类,其中包括了 通用寄存器,乘除法单元,访存单元(含内存),分支控制单元,浮点单元,向量单元;并且包含对这些单元的操作方法。
只要外面再加一层封装,初始化某一块只读的内存单元,其中装载固件,然后操作这个cpu,取指令,解析指令并调用这个cpu状态类的相应方法,虚拟机就运行起来了。
对于I/O,可以在访存单元中判定访存地址,来确定实际操作的硬件单元,然后将这些操作映射到我们虚拟的硬件设备上(比如用一个画布类虚拟出来的游戏机屏幕)。
另一种可选方案是,截获用户的所有系统调用,并且在虚拟机中完成这些系统调用请求的功能(硬件I/O,内存管理等)(而不是在虚拟机上运行的固件中完成)。
对于中断,可以作为一个事件传递给cpu实例,要求其作出适当响应。
指令的异常可以作为exception给throw出去。
相关文章推荐
- 状态状态机Qwt源码解读之QwtPickerMachine类
- jpcsp源码解读之一:源码的获取与编译,以及psp详尽硬件信息文档
- jpcsp源码解读11:近期笔记
- JPCSP源码解读16:HLE与模块装载过程
- jpcsp源码解读之二:main函数与jpcsp的初始化流程
- jpcsp源码解读13:动态二进制翻译1
- Flink-CEP论文与源码解读之状态与状态转换
- jpcsp源码解读之三:Screen类
- jpcsp源码解读之四:Clock类
- jpcsp源码解读5:umd光盘镜像(.iso)
- JPCSP源码解读15:动态二进制翻译3(翻译引擎最终章)
- jpcsp源码解读12:本地码管理器与Compiler.xml
- JPCSP源码解读14:动态二进制翻译2
- jpcsp源码解读9:指令的抽象描述与指令的译码
- jpcsp源码解读7:HLE
- jpcsp源码解读6:PSF文件
- nginx中CPU亲和性源码解读
- nginx中CPU亲和性源码解读
- Silverlight实用窍门系列:25.Silverlight多线程技术Timer的应用,模拟心电图、模拟CPU、内存状态图【附带源码实例】
- jpcsp源码解读10:指令的执行