Teak DSP 片上仿真模块(OCEM)调试寄存器详解:melonDS/Teakra 项目中的 MMIO 布局与程序/数据断点机制

原创2026-10-03 09:39:371,379 阅读
文章标签:虚拟化JIT编译图形学

Teak DSP 片上仿真模块(OCEM)调试寄存器详解:melonDS/Teakra 项目中的 MMIO 布局与程序/数据断点机制

本指南以 melonDS 仓库内嵌的 Teakra 子项目文档 ocem.md 为主体,系统讲解 XpertTeak(DSi/3DS 内置 DSP)片上仿真模块(On-chip Emulation Module,OCEM)的完整 MMIO 布局、每一条调试寄存器的位语义,以及它们与程序断点、数据断点、程序流跟踪和断点状态报告之间的配合关系。读完本文,你将掌握 OCEM 各寄存器(+0x0060 ~ +0x006F)的字段构成与使用时机,并能结合 mmio.md、mmio.cpp 理解该模块在仿真器中的落地现状。

OCEM 在 Teak 调试体系中的定位

在 Teak(XpertTeak)架构中,处理器核心通过 MMIO 与外设(以及间接地、通过外设与主机 CPU 通信)打交道。MMIO 区域在 16 位地址空间中占据 0x0800 个字的区间,默认起始地址为 0x8000,其基址可以通过 MIU(Memory Interface Unit)的 MIU_MMIOBASE 寄存器(解析度为 512 字)重定位;MMIO 寄存器通常只使用偶地址,这一约束甚至可以通过 MIU 中的寄存器强制实施(见 mmio.md)。整个 MMIO 区域按外设划分为若干子区域,OCEM 正是其中之一:

MMIO 偏移 外设 全称
+0x0000 (未知) —
+0x0004 JAM —
+0x0010 GLUE —
+0x0020 Timer 定时器
+0x0050 SIO Serial IO,串行 IO
+0x0060 OCEM On-chip Emulation Module,片上仿真模块
+0x0080 PMU Power Management Unit,电源管理单元
+0x00C0 APBP Advanced Peripheral Bus Port
+0x00E0 AHBM Advanced High Performance Bus Master
+0x0100 MIU Memory Interface Unit,存储接口单元
+0x0140 CRU Code Replacement Unit,代码替换单元
+0x0180 DMA Direct Memory Access,直接内存访问
+0x0200 ICU Interrupt Control Unit,中断控制单元
+0x0280 BTDMP Buffered Time Division Multiplexing Port

OCEM 的职责是面向调试(仿真/片上调试器):它集中提供程序地址断点、数据地址断点、数据值断点、程序流跟踪(Program Flow Trace,PFT)以及各类断点触发状态的回读。所有寄存器地址都是相对 MMIO 区域起始地址的偏移。

需要特别说明的一个硬件特性是:OCEM 是整个 Teak MMIO 空间中唯一使用奇数地址寄存器的区域。ocem.md 的作者在文档开头注明,其 MMIO 定义源自 Lauterbach 的 Teak 调试器,并根据 Teak 架构做了修正,其中围绕程序地址断点的不同布局经过了实测验证(the different layout around program address breakpoint is tested)。

OCEM 的 MMIO 布局总览

OCEM 的寄存器区从偏移 +0x0060 延伸到 +0x006F,共 16 个寄存器地址(0x0060 ~ 0x006F),每个寄存器为一个 16 位字。整体布局如下(源自 ocem.md 的原始定义,表格中 +0x00xx 为相对 MMIO 基址的偏移,每格为一组 4 个 bit 位):

+-----------#---+---+---+---#---+---+---+---#---+---+---+---#---+---+---+---#
|+0x0060    |                              PFT                              |
+-----------#---+---+---+---#---+---+---+---#---+---+---+---#---+---+---+---#
|+0x0061    |                                                               |
+-----------#---+---+---+---#---+---+---+---#---+---+---+---#---+---+---+---#
|+0x0062    |                             PAB1_L                            |
+-----------#---+---+---+---#---+---+---+---#---+---+---+---#---+---+---+---#
|+0x0063    |               |      PAP1     |                       |PAB1_H |
+-----------#---+---+---+---#---+---+---+---#---+---+---+---#---+---+---+---#
|+0x0064    |                             PAB2_L                            |
+-----------#---+---+---+---#---+---+---+---#---+---+---+---#---+---+---+---#
|+0x0065    |               |      PAP2     |                       |PAB2_H |
+-----------#---+---+---+---#---+---+---+---#---+---+---+---#---+---+---+---#
|+0x0066    |                             PAB3_L                            |
+-----------#---+---+---+---#---+---+---+---#---+---+---+---#---+---+---+---#
|+0x0067    |               |      PAP3     |                       |PAB3_H |
+-----------#---+---+---+---#---+---+---+---#---+---+---+---#---+---+---+---#
|+0x0068    |                               |             PACNT1            |
+-----------#---+---+---+---#---+---+---+---#---+---+---+---#---+---+---+---#
|+0x0069    |                               |             PACNT2            |
+-----------#---+---+---+---#---+---+---+---#---+---+---+---#---+---+---+---#
|+0x006A    |                               |             PACNT3            |
+-----------#---+---+---+---#---+---+---+---#---+---+---+---#---+---+---+---#
|+0x006B    |                              DAM                              |
+-----------#---+---+---+---#---+---+---+---#---+---+---+---#---+---+---+---#
|+0x006C    |                              DAB                              |
+-----------#---+---+---+---#---+---+---+---#---+---+---+---#---+---+---+---#
|+0x006D    |SSE|ILE|BRE|TBE|INE|BRE|P3E|P2E|P1E|EXR|EXW|CDE|DAR|DAW|DVR|DVW|
+-----------#---+---+---+---#---+---+---+---#---+---+---+---#---+---+---+---#
|+0x006E    |DBG|BOT|ERR|MVD|                                           |TRE|
+-----------#---+---+---+---#---+---+---+---#---+---+---+---#---+---+---+---#
|+0x006F    |SFT|ILL|TBF|INT|BR |           |PA3|PA2|PA1|ABT|ERG|CD |DA |DV |
+-----------#---+---+---+---#---+---+---+---#---+---+---+---#---+---+---+---#

这些寄存器可以按功能归为四组:

  1. 程序断点与跟踪组(+0x0060 ~ +0x006A):PFT、PAB1_L/H、PAB2_L/H、PAB3_L/H、PAP1~PAP3、PACNT1~PACNT3;
  2. 数据断点组(+0x006B ~ +0x006C):DAM、DAB;
  3. 断点控制位(+0x006D):DVW、DVR、DAW、DAR、CDE、EXW、EXR、P1E、P2E、P3E、BRE、INE、TBE、ILE、SSE;
  4. 状态与事件标记(+0x006E ~ +0x006F):DBG、BOT、ERR、MVD、TRE,以及 SFT、ILL、TBF、INT、BR、PA3、PA2、PA1、ABT、ERG、CD、DA、DV。

下面逐组展开,并对接 Teak 架构背景(见 processor_general.md)说明其语义。

程序断点与程序流跟踪寄存器(+0x0060 ~ +0x006A)

Teak 处理器采用独立的指令/数据地址空间:指令地址为 (18+4) 位,其中低 18 位由程序计数器直接寻址,高 4 位由 prpage 寄存器指定,因此程序存储器理论上有 16 页、每页至多 0x40000 字;而 DSi/3DS 实际只提供半页(0x20000 字),prpage 恒为 0。数据地址为 16 位(0x10000 字),DSi/3DS 则提供 0x20000 字的扩展数据内存并通过 MIU 的存储体切换访问(详见 miu.md)。OCEM 的程序断点正是针对"页 + 页内地址"这一二维程序地址空间设计的。

寄存器 全称 位宽 语义
PFT Program Flow Trace 16 位(+0x0060) 程序流跟踪。跟踪缓冲区满(TBF)时停止写入,调试器可从此处读出程序执行轨迹
PAB1_L / PAB1_H Program Address Break Point #1 各 16 位/4 位(+0x0062/+0x0063 低 4 位) 程序地址断点 #1 的地址。PABx_L 为低 16 位,PABx_H 为高 4 位(拼接成 20 位程序地址)
PAB2_L / PAB2_H Program Address Break Point #2 同上(+0x0064/+0x0065) 程序地址断点 #2
PAB3_L / PAB3_H Program Address Break Point #3 同上(+0x0066/+0x0067) 程序地址断点 #3
PAP1 / PAP2 / PAP3 Program page for PAB #1/#2/#3 各 6 位(+0x0063/+0x0065/+0x0067 中段) 对应程序地址断点的程序页号。文档以 (?) 标注,表示其精确语义尚未完全确认
PACNT1 / PACNT2 / PACNT3 Program Address Break Point Counter 各 14 位(+0x0068/+0x0069/+0x006A 低 14 位) 程序地址断点计数器,可实现对"命中 N 次后才触发"这类条件断点的支持

关键结构信息(均来自 ocem.md 的布局图):

  • PABx 是 20 位地址、跨两个寄存器存放:PABx_L 占满 +0x0062/0x0064/0x0066 整个 16 位字;PABx_H 只占用 +0x0063/0x0065/0x0067 的低 4 位,高 6 位与 PAPx 上方的 6 位均为保留位。
  • PAPx 与 PABx_H 共用一个寄存器字:+0x0063/0x0065/0x0067 的中间 6 位是程序页号(PAPx),低 4 位是 PABx_H。这与 Teak "页 + 页内地址" 的程序地址模型相吻合:PABx_H 对应 PC 的 18~21 位(prpage 侧),PAPx 对应更高位的页选择。
  • PACNT 使用 14 位,寄存器字高 2 位保留,可与事件标记寄存器 +0x006F 中的 PA1/PA2/PA3 位配合,实现计数到后触发断点。

数据断点寄存器(+0x006B ~ +0x006C)

寄存器 全称 位宽 语义
DAM Data Address Mask 16 位(+0x006B) 数据地址掩码。与 DAB 配合实现"地址范围/掩码匹配"式的数据断点,常用于按地址区间或忽略低位地址的匹配
DAB Data Address Break Point 16 位(+0x006C) 数据地址断点。与 DAM 掩码比对后命中,即可触发数据地址断点

DAM/DAB 的匹配结果会被 DAW/DAR 使能位接纳为断点条件,命中后会在 +0x006F 中置起 DA(匹配数据地址)等标记位。

断点控制寄存器 +0x006D:16 个使能位

+0x006D 一个寄存器字容纳了 16 个单 bit 的断点使能控制位,按高位到低位排列如下:

位名 置 1 时的行为
DVW 在数据写事务上使能数据值断点
DVR 在数据读事务上使能数据值断点
DAW 在数据写事务上使能数据地址断点
DAR 在数据读事务上使能数据地址断点
CDE 使能"数据地址与数据值同时匹配"才触发的断点(组合条件断点)
EXW 因外部寄存器写事务使能断点
EXR 因外部寄存器读事务使能断点
P1E 使能程序断点 #1
P2E 使能程序断点 #2
P3E 使能程序断点 #3
BRE 使能"程序每次跳转(而非顺序执行下一条地址)时触发"的断点
INE 检测到中断服务例程时使能断点
TBE 因程序流跟踪缓冲区已满(trace buffer full)使能断点
BRE 使能"返回到块重复循环(block repeat loop)开头时触发"的断点
ILE 在非法条件(illegal condition)上使能断点
SSE 使能单步(single step)执行

值得注意的细节:+0x006D 中存在两个同名位 BRE(分别对应"每次跳转触发断点"与"块重复循环返回开头触发断点"两种不同事件)。这是 ocem.md 原始文档的写法;由于 Teak 的块重复机制(block repeat)与分支跳转是两类不同的控制流事件,文档作者可能用同一个缩写指代两个物理位置不同的控制位。在按位读写该寄存器时,应留意这两个位在字中的位置不同(一个靠近位 13 一侧,一个靠近位 10 一侧,具体以实际布局图为准)。

状态寄存器 +0x006E:调试器可见的处理器状态

+0x006E 是只读/状态类寄存器,高 4 位为状态标志,低 1 位为跟踪组合标志,中间 11 位保留:

位名 置 1 时的含义
DBG 指示当前处于调试模式(debug mode)
BOT 指示当前处于引导模式(boot mode)
ERR 检测到:在执行断点服务例程期间激活了用户复位(user reset)
MVD 检测到执行了 MOVD 指令
TRE 指示当前 TRACE 条目必须与下一条 TRACE 条目合并(组合成一条完整记录)

其中 ERR 位描述的是一种调试器特有的竞态场景:当处理器停驻在断点服务例程(break point service routine)时,若主机又发起了用户复位,该事件被记录为 ERR。TRE 位则服务于程序流跟踪的成帧:某些控制流事件(如双字指令或跳转目标)需要两条 TRACE 条目合并解释,TRE 即标记此组合关系。

断点事件标记寄存器 +0x006F:命中原因回读

+0x006F 汇总了最近一次断点/异常事件的触发来源。调试器在断点停驻后读取该寄存器,即可判断"为什么停下来",从而决定下一步处理(这也是 icu.md 描述的中断服务流程之外的、面向调试器的另一套事件报告通道):

位名 置 1 时的含义
SFT 检测到软件陷阱(software trap)
ILL 检测到非法断点(illegal break point)
TBF 程序流跟踪缓冲区已满(Trace Buffer Full)
INT 检测到中断断点(interrupt break point,配合 INE 使能)
BR 检测到分支断点(branch break point,配合 BRE 使能)
PA3 检测到程序地址断点 #3 命中(配合 P3E 使能)
PA2 检测到程序地址断点 #2 命中(配合 P2E 使能)
PA1 检测到程序地址断点 #1 命中(配合 P1E 使能)
ABT 因外部事件(external event)检测到断点
ERG 因用户定义的寄存器事务检测到断点(配合 EXW/EXR 使能)
CD 因数据值与数据地址同时匹配检测到断点(配合 CDE 使能)
DA 因数据地址匹配检测到断点(配合 DAW/DAR 使能)
DV 因数据值匹配检测到断点(配合 DVW/DVR 使能)

由此可以看出 OCEM 断点机制的整体分工:+0x006D 决定"什么事件被允许成为断点"(使能),+0x006E 提供"当前处理器处于什么模式"(状态),+0x006F 报告"本次断点由哪个事件引起"(命中原因)。三者配合 PABx/PAPx/PACNTx(程序断点)与 DAM/DAB(数据断点),即可实现功能完整的片上调试会话。

结合源码看 OCEM 的仿真实现现状

从源码层面看,Teakra 的 MMIO 实现位于 mmio.cpp:MMIORegion 内部通过一个 0x800 个 Cell 的数组模拟整个 MMIO 地址空间(std::array<Cell, 0x800> cells),读写统一走 MMIORegion::Read/Write(mmio.cpp)。Cell 支持多种构造方式:RefCell(直接绑定到状态变量)、ConstCell(固定常量,如 +0x01A 处的芯片检测值 0xC902)、MirrorCell(寄存器镜像)以及 BitFieldCell(按位字段拆分读写,如 Timer、ICU 的矢量寄存器等)。

在该构造函数中,已实现的子区域包括 Timer(+0x20)、APBP(+0xC0)、AHBM(+0xE0)、MIU 的部分寄存器(+0x10E ~ +0x11E)、DMA(+0x184 ~ +0x1DE)、ICU(+0x200 ~ +0x214+N*4)与 BTDMP(+0x282 起)。OCEM 区域(+0x0060 ~ +0x006F)目前没有对应的 Cell 注册条目——从源码结构看,Teakra 仿真器尚未实现该模块的断点/跟踪行为,这也与 OCEM 主要用于调试器(Lauterbach 等外部工具)而非 DSP 正常运行路径的定位一致。文档中给出的布局主要价值在于:

  1. 作为后续实现 OCEM 的寄存器映射蓝图(哪个偏移对应哪个字段、位宽如何);
  2. 为复现/验证真实硬件调试行为提供可对照的位级定义;
  3. 与 miu.md、icu.md 等外设文档一起,构成完整的 Teak MMIO 寄存器手册,方便对 XpertTeak 进行逆向与仿真。

小结

OCEM 是 Teak DSP 调试基础设施的核心,其 +0x0060 ~ +0x006F 寄存器区浓缩了程序地址断点(3 组,含页号与计数器)、数据地址/数据值断点(含掩码)、程序流跟踪以及一套完整的断点使能/状态/命中原因报告机制,并且是 MMIO 中罕见的含奇数地址寄存器的区域。本文基于 ocem.md 完整还原了其布局与位定义,并结合 processor_general.md(程序地址空间模型)、mmio.md(MMIO 分区)、miu.md(存储接口与分页)与 mmio.cpp(仿真实现现状)给出了跨文档的上下文。对于希望深入了解 XpertTeak 调试机制或为 Teakra 补齐 OCEM 支持的研究者,这份位级定义是可直接参考的起点。

登录后查看全文
melonDS