测试ARM CPU仿真器

时间:2013-01-27 23:08:00

标签: c assembly arm emulation

我目前正在编写Gameboy Advance模拟器,纯粹是为了好玩。它有一个ARM7TDMI CPU,我编写了大部分CPU仿真代码。我的问题是,如何进行测试呢?

在随机GBA软件上测试它并没有太大的帮助 - 程序可能会因为与CPU无关的原因而崩溃,最好一块一块地测试,而不是一起测试。

是否有可用的程序来测试ARM CPU,尤其是指令集?我查看了几个ARM模拟器的来源,但还没找到我想要的东西。如果没有,我将编写自己的程序,但很难使测试全面。

提前致谢!

3 个答案:

答案 0 :(得分:1)

如果您的目的是编写一个完整的系统仿真器,我会找出您需要至少支持的其他系统,并在您担心CPU仿真是否有效之前实现它们。想象一下图形和内存控制器是最重要的。它们也更容易编写单元测试,如果你能说服自己工作正常,那么你将拥有适当的工具来测试你的CPU模拟。

话虽如此,如果您想首先测试CPU仿真,我会添加一些调试代码来反汇编指令并在每个寄存器之前打印所有寄存器的值(以及它们可能指向的内存中的值)指令。然后尝试运行一些游戏。即使它们不会走得太远,你也会有一个巨大的数据库来评估仿真代码是否正在对寄存器/内存状态进行正确的更改。

答案 1 :(得分:1)

QEMU非常适合ARM CPU /指令集。 Balau是开始的好文章。 QEMU可以为许多广泛使用的硬件平台提供Linux,甚至可以为少数ARM硬件平台提供U-Boot /裸机代码。

y对于您的Gameboy模拟器,您的图形将如何显示?

答案 2 :(得分:1)

我同意R.首先测试cpu,和/或与模拟硬件分开测试。有一个坚实的基础开始。

我有两个书面指令集模拟器,并测试它们以及正在开发的实际处理器。

有明显的定向测试,针对特定的指令来确定它们的工作原理。仔细看一下ARM文档,例如,shift有if-then-else定义,如果shift等于32然后不转换或类似的东西,创建一个测试来验证if-then-else中的每个条件。

无论什么指令集(除了没有标志的那些)之外,标志总是很棘手。使您的有符号和无符号溢出正确(进位=无符号溢出)以进行添加。然后弄清楚目标处理器如何处理减法。通常你想要反转进位和第二个操作数(进入加法器),其中一个结构与另一个结构不同是执行,有些反转执行减法,有些不执行。如果有一个带有借位指令的减法,则无论执行规则如何影响带有借位的减法,无论它是否反转进位。幸运的是有C编译器可以帮助解决这个问题,假设它们的输出与实际处理器相反(部分原因) job正在从处理器错误中挑选出编译器错误,并且你会遇到编译器错误)。全零(全部为1)和全零(0x80000000)的特殊情况应该进行定向测试以确保它们的(已签名)溢出正常工作。有些操作只会影响某些标志,或者某些操作会影响某些标志等。请确保创建情境以进行测试。 ARM还允许任何指令是条件的,并且alu指令可选地修改标志,从而使情况变得更糟。

我喜欢使用zlib和jpeg解码器,mp3解码器,任何开源的东西,可以用裸机方式编译(是的,这些已经提到过了!),这意味着没有操作系统。现在,zlib在混合long和int时是一个噩梦,所以取决于你的编译器当天在主机上的工作方式(一些编译器,有时使用主机架构来调整变量而不是目标架构时)交叉编译,这很烦人)。我甚至会为所有类型的跳转调用zlib bug,所以我已经减少了使用它进行测试,因为调试编译所花费的时间而不是它返回的值推动处理器,因为它没有推动处理器很难(虽然我发现处理器错误使用它)。对于有损的jpeg和mp3解码器,您需要在主机上计算的预先计算的答案。除非你想使用软浮点数,否则你需要整数解不浮点。

当使用编译器进行测试时,要了解一些事情,首先要尝试所有的优化,因为每个编译的测试都有-O0,-O1,-O2和-O3版本,因为它会创建不同的指令混合并以不同的方式推动处理器。小心虽然这是你可能开始遇到编译器错误的地方。同一编译器和不同编译器的不同版本产生不同的输出,不同的指令混合,如果可能的话,最好能够获得尽可能多的不同编译器,使用evals或其他任何东西。在评估编译器时,我发现了一些编译器错误,他们给了我一段时间的完整版本的免费副本。因人而异。此外,对于您来说可能是不可能的,不同的个体(不受编码标准严格控制)产生不同的指令混合(asm或更高),在您完成每条指令后,理论上,在隔离时工作,您可能会发现有当某个指令跟随另一个指令时仍然存在错误,因此尝试创建指令混合是有用的,即使你从未发现错误它是一个很好的验证。我已经提到了编译代码,但是你可能也想要使用随机函数来创建一系列alu操作来选择操作以及源和目标寄存器(使用混合标记的操作)并且如果可能的话运行该代码在真正的处理器上然后在你的处理器上运行它,看看你是否得到相同的结果。

我工作的一个处理器我们在硬件中构建了一个测试夹具,我可以在测试夹具中与外围设备通信,1)允许我以某种速率发送中断2)为特定地址创建数据/预取中止。所以我接受了一个zlib测试,当它运行的时候我用中断敲了一下,然后在中断中我查看了指令的返回地址,然后用一个预取中止了几句话,有时它们有时不打,这很好,重要的是让主应用程序尽管中断仍然完美运行(我会让中断继续正常,中止将撤防,备份并让它再试一次)。至少你应该能够通过中断攻击你的测试应用程序,并确保他们继续使用卡车。

不幸的是,GBA中的大部分逻辑都是图形方面,所以即使你在处理器上付出了很多努力,你仍然需要调试图形。您可以通过在伪内存解码器上放置测试接口来隔离该代码,并让主机应用程序访问虚拟外设,而不是总是模拟arm代码来执行此操作。在一天结束的时候,虽然我认为它正在推出最难以推动的架子游戏,但调试问题可能非常困难。我认为拥有一个坚固的手臂核心可以使调试变得更容易,不用担心,减少一个问题来源。

另一个问题是,由于gba的设计方式,通过在拇指模式下运行手臂可以显着提升性能,因此您将看到许多拇指模式程序,这是验证/调试的更多手臂核心内容。混合模式等