Gdb/Armulator 源代码分析
(大家注意到18行也调用了ARMul_Reset(…),这是一个BUG,使得模拟器进行了两次内存分配,而浪费了系统内存.此处可删去.)
Memory map 是所有模拟器的关键.Armulator由AT91向其他MCU移植时Memory map又是首先要处理的.Armulator的各个内存区是由mem_bank_t结构来描述的:
typedef struct mem_bank_t {
ARMword (*read_word)(ARMul_State *state, ARMword addr);
void (*write_word)(ARMul_State *state, ARMword addr, ARMword data);
unsigned long addr, len;
char *filename;
} mem_bank_t; file://定义在armmem.h中
Armulator的整个内存则是又此结构的数组static mem_bank_t mem_banks[]管理的.
AT91的memory map如下:
static mem_bank_t mem_banks[] = {
/* the yuk's below are to work around a uClinux/mount options problem */
{ real_read_word, real_write_word, 0x01000000, 0x00400000, }, /* 2.4 */
{ real_read_word, _write_word, 0x01400000, 0x00400000, "boot.rom"},
{ real_read_word, real_write_word, 0x02000000, 0x00400
000, }, /* 2.0 */
{ real_read_word, real_write_word, 0x02400000, 0x00001000, }, /* yuk!*/
{ real_read_word, _write_word, 0x04000000, 0x00400000, "boot.rom"},
{ real_read_word, real_write_word, 0x00000000, 0x00004000, },
{ io_read_word, io_write_word, 0xf0000000, 0x10000000, },
{ fail_read_word, fail_write_word, 0, 0 }
};
根据mem_banks,mem_reset( )将分配空间,加载boot.rom文件.
(原来的内存是由ARMul_MemoryExit( )释放的,但补丁后的代码就没了释放功能,这也是需要纠正的地方)
a. 指令流
Armulator 加载完成后,就开始等待Gdb的运行命令了.最终/sim/wrapper.c/sim_resume( )是启动arm指令执行的地方.
Sim_resume( )根据Gdb的要求选择用/sim/arm/arminit.c/ARMul_DoInstr()还是用/sim/arm/arminit.c/ARMul_DoProg()来调用 流水线模拟函数/sim/arm/armemu.c/ARMul_Emulate32().ARMul_DoInstr()和ARMul_DoProg()的区别就是一个单步执行,一个连续执行指令. ARMul_DoProg()又不停的判断state->Emulate是否为STOP,如果是,模拟器又将停下等待Gdb的调试.
而在arm/armemu.c, /arm/armvirt.c 和 /arm/armsupp.c中的函数则模拟指令预取,指令译码,指令执行以及数据回写的功能.这三个文件时可以说时Armulator的核心!
b. 中断
Armulator 的中断机制主要靠以下两个例程实现:
1.IntPending(): 用来检测state中的各个中断标志是否置位,从而判断是否又需要中断.
《Gdb/Armulator 源代码分析(第3页)》