大多数组件被组合成一个名为CPU AGB的单一封装。 该封装包含两个完全不同的CPU:
- 运行频率为8.4或4.2MHz的夏普SM83:这不就是Game Boy上发现的同一款CPU吗!它可有效运行Game Boy(DMG)和Game Boy Color(CGB) 游戏。 如果您想了解有关这些游戏机的更多信息,请参阅我以前的文章。
- 运行频率为16.78 MHz的ARM7TDMI: 这是我们要重点介绍的新处理器,它肯定能运行Game Boy Advance游戏。
不过,这两块CPU永远不会同时运行,它们也不是什么协处理器。 搭载这颗极其老旧的夏普芯片的唯一理由只是为了向后兼容。
话虽如此,在介绍ARM芯片之前,我还是想先介绍一下该品牌CPU的历史。
剑桥奇迹
有关ARM CPU的起源及其后来声名鹊起的故事引人入胜。 在这里,我们看到了公共投资、指数式增长、错误决策和远距离合作的结合。
Acorn电脑的崛起

BBC Micro的照片,上面有一盒5.25英寸磁盘,第一张磁盘是Elite(1984年发行的游戏)。
70年代末对英国民众来说是一个动荡的年代。 曾经在战后理想下建立起来的干预主义经济已经走到了尽头,钟摆很快摆向了自由市场改革。 在这场风暴中,以剑桥为基地的企业,如Acorn Computers,与Sinclair等公司一起,向实验室和业余爱好者销售计算机套件。 与美国和日本企业类似,Acorn计算机也依赖于6502 CPU和专有的BASIC语言。
进入上世纪80年代,英国新政府的大臣们开始在学校开展计算机扫盲项目。 由于Acorn即将推出"质子"(Proton)家用电脑,该公司获得了制造经济型电脑的合同,以实现政府的愿景。 结果,BBC Micro(昵称 "Beeb")在学校、教师和学生中获得了巨大成功。 在Micro中,Acorn采用了前卫的"Tube"接口,可以通过第二个处理器扩展计算机。 这为Acorn的下一项重大投资铺平了道路。
在开发下一款以企业为重点的产品时,Acorn没有找到合适的CPU来接替6502。 面对日本和美国的竞争,Acorn面临着创新的压力,再加上计划不周,Acorn 的财务状况陷入了困境。 因此,Acorn成立了一个新的部门,负责生产引人注目的CPU。 为了绕过Acorn最近的限制,CPU团队根据一篇名为《精简指令集计算机案例》的研究论文及其原型RISC CPU,建立了自己的架构。 最后,在1985年,Acorn将ARM1 CPU作为BBC Micro的Tube模块交付使用,但仅用于研发目的的市场推广。 直到1987年,随着第一台Acorn Archimedes计算机的推出,ARM芯片(当时为ARM2 CPU)才开始占据核心地位。
新的CPU风险投资

苹果Apple Newton的晚期型号......在我玩过之后。
在Acorn Archimedes的商业化过程中,苹果公司被Acorn的高能效CPU所吸引,但这家美国公司仍然不相信Acorn最新的ARM3会适合苹果公司的新项目Newton。 不过,双方并没有放弃(毕竟Acorn是竞争对手),而是讨论了改进ARM3以满足苹果要求的可能性,即可变时钟频率、集成MMU和完整的32位寻址。
这种合作很快变成了一种伙伴关系,Acorn、苹果和VLSI(ARM芯片制造商)成立了一家新公司,专门致力于开发ARM CPU。 苹果公司提供投资(获得43%的股份),Acorn公司分担员工,VLSI公司负责生产。 1990 年,Advanced RISC Machines(ARM)公司成立,Robin Saxby担任执行董事长。
数年后,苹果终于推出了采用ARM610的Newton MessagePad。ARM610是新一代ARM芯片之一,集成了苹果的投入。 与此同时,Acorn也发布了使用新CPU的RiscPC。
现在,当Acorn和苹果在电脑/手持设备市场上徘徊不前时,ARM却设计出了一种激进的商业模式。 Saxby的愿景是远离制造业,以CPU设计和指令集的形式授权ARM的知识产权。 这使ARM获得了计算机领域以外的客户,如德州仪器,后者后来将公司与新兴的移动市场(最终推出了诺基亚6110)和机顶盒联系起来。 在接下来的几年中,ARM的技术将被捆绑到数十亿台移动设备中。
任天堂的合作伙伴关系
回到日本,通过对Game Boy的分析,我们了解到任天堂的便携式系统硬件战略倾向于采用片上系统(System On a Chip,SoC)模式。 这使该公司能够将负担得起的现成技术模糊化,并与内部开发相结合。 这样,新游戏机就可以独树一帜,具有竞争力。

CPU AGB,内含ARM7TDMI CPU(以及许多其他组件)。
幸运的是,ARM的许可模式正好满足了这些需求。 两家公司从1994年(Virtual Boy推出的前一年)起就开始了谈判,但直到多年后才有了结果。 原因很简单:日本人认为ARM的代码密度和对32条数据线的需求不可行(Virtual Boy的CPU已经成功摆脱了这一点)。 尽管如此,ARM的新CPU设计师Dave Jaggar很快就推出了ARM7TDMI,这款新CPU的重点是在功耗和存储限制条件下最大限度地提高性能。 这对ARM来说是一个转折点,因为这款新产品不仅让任天堂感到高兴,还引起了德州仪器、诺基亚和手机领域其他竞争对手的注意。
不出所料,当任天堂开始开发Game Boy Color的后续产品时,他们选择的CPU变成了ARM7TDMI。
ARM7TDMI
现在让我们深入了解一下这款芯片的功能。
指挥 CPU
首先,ARM7TDMI实现了ARMv4指令集,即ARMv3的后续版本。 这意味着:
- 基于RISC的设计: 如前所述,ARM CPU受到了加州大学伯克利分校一篇名为《精简指令集计算机案例》的论文的影响。 该论文概述了一系列可扩展处理器设计指南,并为使用存-取架构、固定指令大小和大型寄存器文件进行辩护。 在当时的CPU市场(即英特尔 8086、MOS 6502、Zilog Z80和摩托罗拉 68000)中,许多指令集都不存在,但在整个 80 年代和 90 年代,这些指令集对新CPU系列的设计产生了影响。
- 条件执行:ARM ISA的一个特殊功能。 从本质上讲,几乎每条指令都包含一个条件,说明是否应该执行。 通常,其他CPU遵循"比较和跳转"过程(也称为 "分支")来控制CPU必须执行哪些指令。 相比之下,ARM程序员可以在指令本身插入条件。 这是因为ARM操作码的前四位保留给了条件(即
等于、不等于等)。 总而言之,这降低了ARM代码的复杂性,因为与分支和子程序分割不同,条件执行提供了更简洁的例程设计。 此外,这也是控制冒险的一种解决方法(稍后会有更详细的解释)。 - 灵活的第二操作数,也称为"Operand2"。 通常,操作由两个操作数构成(例如将2与2相加)。 然而,ARM指令还允许在第二个操作数中嵌入额外的移位(
shift)操作。 例如,您可以在一条指令中完成将2移位四位后再与2相加的计算。- 移位操作也是一种利用2的幂次进行除法或乘法运算的高效捷径,这一特性催生了许多优化技术。
- 32位和64位乘法指令:这是ARM v4的新增功能。 此外,64位运算将结果输出到两个寄存器中。
封装
既然我们已经知道了开发人员如何与芯片对话,那就来看看芯片内部有什么吧。
核心
就电路而言,ARM7TDMI是ARM710的缩小版,但增加了一些有趣的功能。 该核心包括 :
- 16个通用32位寄存器: 虽然与SM83/Game Boy的7个8位寄存器相比,这是一个很大的进步,但这是对RISC准则的妥协,因为 RISC 准则要求32个32位寄存器。 这是因为ARM希望保持较小的芯片尺寸。
- 32位数据总线和ALU:这意味着它可以在不消耗额外周期的情况下移动和操作32位数值。
- 干净的32位寻址: 这是苹果投入的一部分。 前三代ARM CPU使用26位内存地址来优化性能(程序计数器和状态寄存器可合并为一个32位字),以换取内存寻址能力(最多可访问64 MB内存)。 后续的ARM6系列(采用ARMv3 ISA)实现了32位寻址逻辑,但为旧代码保留了向后兼容模式。 现在,ARM7TDMI(专注于移动设备)取消了26位模式,只保留了32位寻址逻辑(减少了所需硅的面积)。
- 无内存管理单元 (MMU): 从ARM1开始,ARM就提供了MMU解决方案。 首先是作为"MEMC"协处理器,然后与ARM610集成。 现在,ARM7TDMI似乎是其系列中唯一不提供MMU的产品,这可能是由于缺乏兴趣(早期的移动设备不需要复杂的虚拟内存)。
- 无缓存: 这是该芯片降低成本的另一个原因,因为以前的ARM芯片都捆绑了一些缓存。
最后,所有这些都可以在3V电源下运行。 这显然是向移动计算迈出的一步,因为早期的内核需要5V电源。
流水线
从第一次迭代开始,ARM就采用了三级流水线来运行代码。 换句话说,指令的执行分为三个步骤或阶段。 CPU能够同时对三条指令进行取指、译码与执行操作。 这样一来,CPU能够最大化地利用自身资源 (缩短闲置时间)、提升吞吐率。
与同时代的两个非常相似的处理器一样,ARM CPU也容易受到数据冒险的影响。 不过,程序员和编译器都不会注意到,因为在这种情况下,CPU会在需要时自动停止流水线。
控制冒险也同样存在,但ARM采用了一种名为条件废止(conditional annulment)的有效方法来解决它们: 每当分支指令处于第二阶段(解码)时,CPU 就会计算分支的条件。 根据计算结果,如果必须执行分支指令,CPU将自动取消后续指令(将其变为填充指令)。 现在,与MIPS的方法相比(因为MIPS编译器可以插入有用的指令,而不仅仅是填充指令),这种方法可能显得效率不高。 因此,除了分支外,ARM还提供了条件执行。 后者将这种流水线设计变成了一种优势,因为ARM可以在同一流水线阶段对指令进行解码并计算其嵌入条件。 因此,在这种情况下,无需添加填充指令。 这就是为什么在为ARM CPU编程时,条件执行比分支更受欢迎的原因。
挤压性能
存-取架构的缺点之一是ARM的代码非常稀疏。 x86等竞争对手可以使用更少的代码执行相同的任务,所需的存储空间也更小。 因此,当任天堂看到ARM的最新设计ARM7时,他们并不满意。 ARM指令的大小意味着,假设的由16位总线和有限内存及存储空间组成的小工具——所有这些都是为了节约成本和能源——将使CPU效率低下并陷入瓶颈。 幸运的是,Dave Jaggar刚刚完成了ARM7的设计,他还没有放弃。 在与任天堂会面后的通勤途中,他想到了一个解决方案:Thumb指令集。
Thumb是ARM指令集的一个子集,其指令被编码为16位字(而不是32位)。 由于是16位,Thumb指令只需要一半的总线宽度,占用一半的内存。 为实现这一目标,Thumb指令集在以下方面进行了妥协:
- Thumb指令集不支持条件执行,转而依赖分支跳转实现条件逻辑。
- 其数据处理指令操作码仅采用两地址格式(例如
ADD R3, R1,即 R3 = R3 + R1),而非三地址格式(例如ADD R3, R1, R2,即 R3 = R1 + R2)。 - 它仅能访问寄存器组的低半部分(R0-R7)。 因此仅提供八个通用寄存器可用。
总之,由于Thumb指令只提供ARM的一个功能子集,开发人员可能需要编写更多的指令才能达到同样的效果。
实际上,Thumb使用的空间是ARM代码的70%。 对于16位宽内存,Thumb运行速度比ARM快。 如果需要,ARM和Thumb指令可以在同一程序中混合使用(称为互通),这样开发人员就可以选择何时何地使用每种模式。
扩展
ARM7TDMI本质上是一个符合ARMv3标准的附加内核。 后者在其名称(TDMI)中有所提及,意为:
- T->Thumb: 包含Thumb指令集。
- D->调试扩展(Debug Extensions): 提供 JTAG 调试。
- M->增强乘法器(Enhanced Multiplier): 以前的ARM内核需要多个周期才能计算完整的32位乘法运算,这一增强功能将其减少到几个周期。
- I->嵌入式ICE宏单元(EmbeddedICE): 启用硬件断点、观察点,并允许在调试代码时停止系统。 这有助于为该CPU开发程序。
总之,这使ARM7TDMI成为移动和嵌入式设备的一个极具吸引力的解决方案。
内存位置
Thumb的加入尤其对这款游戏机的最终设计产生了很大影响。 任天堂在不同模块之间混合使用16位和32位总线,以降低成本,同时为程序员提供优化代码所需的资源。
Game Boy Advance的可用内存分布在以下位置(从快到慢排列):
- IWRAM(内部WRAM)->32位,32 KB:用于存储ARM指令。
- VRAM(视频 RAM)->16位,96 KB:虽然该块专用于图形数据(将在本文下一节中解释),但它仍位于CPU的内存映射中,因此如果IWRAM不够用,程序员可以存储其他数据。
- EWRAM(外部WRAM)->16位,256 KB:CPU AGB旁边的独立芯片。 它是小块存储纯Thumb指令和数据的最佳选择。 另一方面,该芯片的访问速度比IWRAM慢六倍。
- Game PAK ROM-> 16 位,大小可变: 这是访问卡带ROM的地方。 虽然它可能是速度最慢的存储器之一,但它在内存映射中也有镜像,以管理不同的访问速度。 此外,任天堂还安装了一个预取缓冲器(Prefetch Buffer),与卡带接驳,以减轻过多的卡顿。 当中央处理器不访问卡带时,该组件会独立缓存连续地址,最多可容纳8个16位字。
- 但实际上,CPU很少会让预取缓冲器发挥其作用。 因为默认情况下,CPU会不断从卡带中获取指令以继续执行(这也是IWRAM和EWRAM如此重要的原因)。
- Game PAK RAM->8位,大小可变: 这是访问卡带RAM(SRAM或闪存)的地方
- 这是一条严格的8位总线(CPU会在未使用的位中看到"垃圾"),因此任天堂规定只能通过其库进行操作。
虽然这款游戏机被作为32位系统销售,但其大部分内存只能通过16位总线访问,这意味着游戏大多会使用Thumb指令集,以避免每次指令取用花费两个周期。 只有在非常特殊的情况下(即需要使用Thumb中没有的指令,同时将其存储在 IWRAM中),程序员才会ARM指令集中获益。
成为Game Boy Color
除了包含GBC硬件(夏普SM83、原始BIOS、音频和视频模式、兼容卡带插槽等)外,还需要两个额外功能才能实现向后兼容。
在硬件方面,游戏机依靠开关来检测插入的是Game Boy还是Game Boy Color卡带。 卡带插槽中的形状检测器可有效识别卡匣类型,并允许CPU读取其状态。 假设CPU AGB的某个组件读取了该值,并自动关闭GBC模式下不需要的硬件。
从软件方面来看,有一个名为REG_DISPCNT的16位特殊寄存器可以改变显示屏的许多属性,但其中一位会将游戏机设置为"GBC模式"。 起初,我很难理解GBA究竟何时会尝试更新这个寄存器。 幸运的是,一些开发人员帮我澄清了这个问题:
我认为在GBC启动过程中发生的事情是:检查开关(可在REG_WAITCNT 0x4000204读取),进行淡入(淡入速度非常快,很难察觉),然后最终切换到GBC模式(BIOS写入REG_DISPCNT 0x4000000),停止ARM7。
谜题中唯一缺少的部分是,如果移除GBC卡带外壳的一部分,使开关不再按下,然后通过软件模式切换到GBC模式,会发生什么情况。 多重启动模式在这方面会有所帮助。 我不确定GBC卡带总线是否需要按下开关才能正常工作,或者它只是工作而已。 我猜开关是总线工作的必要条件,但这只是猜测。
- Dan Weiss (又名 Dwedit, PocketNES与Goomba Color的维护人员)
