什么是协处理器?
在 MIPS 早期架构中,为了保持主 CPU(称为“内核”或“核心处理器”)的精简和高效,一些辅助功能被设计成独立的“协处理器”(Coprocessor),协处理器有自己的寄存器和指令集,专门用于处理特定任务,

(图片来源网络,侵删)
- CP0 (协处理器 0): 处理异常、中断、内存管理、缓存控制等系统级任务,它是 MIPS 架构中最重要、最核心的协处理器,没有它,CPU 无法正常运行。
- CP1 (协处理器 1): 通常用于浮点运算(Floating-Point Unit, FPU),它包含用于单精度和双精度浮点数运算的寄存器和指令。
- CP2 (协处理器 2): 在某些特定型号的 MIPS 芯片中,用于特定用途,如图形处理或数字信号处理,但并不通用。
- CP3 (协处理器 3): 历史上曾用于 64 位整数运算,但在现代 MIPS 架构中,其功能已被集成到主 CPU 或其他单元中。
核心要点:
- 协处理器寄存器独立于主 CPU 的 32 个通用寄存器 (
$0-$31)。 - 访问协处理器寄存器需要使用特殊的
MTC(Move To Coprocessor) 和MFC(Move From Coprocessor) 指令。 - 我们将重点讲解最常用和最重要的 CP0 和 CP1。
协处理器 0 (CP0) - 系统控制寄存器
CP0 是 CPU 的“大脑”和“神经系统”,负责管理整个芯片的运行状态,它包含了大量用于控制 CPU 行为、处理异常、管理内存和缓存的寄存器。
1 CP0 寄存器访问指令
MTC0(Move To Coprocessor 0): 将一个通用寄存器的值写入到 CP0 寄存器中。- 语法:
mtc0 $rt, $rd($rd是 CP0 寄存器的编号)
- 语法:
MFC0(Move From Coprocessor 0): 从一个 CP0 寄存器中读取值到通用寄存器中。- 语法:
mfc0 $rt, $rd($rd是 CP0 寄存器的编号)
- 语法:
2 重要的 CP0 寄存器详解
CP0 寄存器通常通过编号来访问,每个编号可能对应多个“选择”(Select)字段,以容纳更多寄存器。
| 编号 | 寄存器名称 | 主要功能 | 关键位/字段 |
|---|---|---|---|
| 12 | Status | CPU 状态和模式控制 | 这是最重要的寄存器之一。 |
| IE (Bit 0): 全局中断使能,为 1 时,CPU 响应中断。 | |||
| EXL (Bit 1): 异常级别,为 1 时,CPU 处于异常处理模式,屏蔽大部分中断。 | |||
| ERL (Bit 2): 错误级别,为 1 时,CPU 处于严重错误模式,屏蔽所有中断。 | |||
KSU (Bits 3-4): 模式选择。00=内核模式,01=用户模式,10=监督模式。 |
|||
| 13 | Cause | 记录异常发生的原因 | 当异常发生时,硬件会自动设置此寄存器以指明原因。 |
| BD (Bit 31): 分支延迟槽异常标志,为 1 表示异常发生在分支指令的延迟槽中。 | |||
| IP (Bits 8-15): 中断挂起位,指示哪些中断源请求服务。 | |||
| ExcCode (Bits 2-6): 异常代码,详细说明异常类型(如中断、TLB 缺失、地址错误等)。 | |||
| 14 | EPC | 异常程序计数器 | 保存发生异常时下一条将要执行的指令的地址。 |
| 用于在异常处理程序返回后,恢复到中断点继续执行。 | |||
| 15 | PRId | 处理器 ID 寄存器 | 标识处理器的型号和制造商。 |
0x00018000 表示是 MIPS32 R1 架构的处理器。 |
|||
| 8 | BadVAddr | 错误地址寄存器 | 当发生地址错误(如 TLB Miss 或总线错误)时,保存导致错误的虚拟地址。 |
| 2, Select 0 | Count | 计数器 | 一个自由运行的 32 位计数器,通常由时钟驱动,常用于实现简单的定时器。 |
| 3, Select 0 | Compare | 比较器 | 与 Count 寄存器比较,当 Count 的值等于 Compare 的值时,会产生一个定时器中断。 |
| 5 | Index | TLB 索引寄存器 | 用于 TLB(Translation Lookaside Buffer,旁路转换缓冲区)的管理。 |
| 6 | EntryLo0 / EntryLo1 | TLB 入口低寄存器 | 存储物理页框号和页属性(如可读、可写、可执行)。EntryLo0 对应偶数索引,EntryLo1 对应奇数索引。 |
| 7 | Random | TLB 随机索引寄存器 | 用于在 TLB 替换算法中随机选择一个条目。 |
| 10 | EntryHi | TLB 入口高寄存器 | 存储虚拟页号和 ASID(地址空间标识符)。 |
3 CP0 工作流程示例:中断处理
- 中断发生:某个硬件(如定时器)发出中断信号。
- 硬件动作:
- CPU 检测到中断,并确认
Status寄存器中的全局中断使能位IE为 1。 - CPU 自动将当前的
PC(下一条指令地址)保存到EPC寄存器。 - CPU 自动设置
Status寄存器中的EXL位为 1,进入异常级别,屏蔽新的中断。 - CPU 在
Cause寄存器的IP字段中标记相应的中断源。 - CPU 跳转到一个固定的内存地址(
0x80000180for MIPS I),该地址是异常入口点。
- CPU 检测到中断,并确认
- 软件处理:
- 异常处理程序开始执行。
- 程序读取
Cause寄存器,判断中断类型。 - 如果是定时器中断,程序会处理定时器相关的任务。
- 处理完毕后,程序执行
ERET(Exception Return) 指令。
- 恢复执行:
ERET指令会执行以下操作:- 从
EPC寄存器恢复PC的值。 - 清除
Status寄存器中的EXL位。
- 从
- CPU 从中断点继续执行原来的程序。
协处理器 1 (CP1) - 浮点单元寄存器
CP1,即浮点单元,专门用于执行浮点数运算,它有两套独立的寄存器:单精度寄存器和双精度寄存器。
1 CP1 寄存器访问指令
MTC1(Move To Coprocessor 1): 将通用寄存器的值写入到 CP1 寄存器中。MFC1(Move From Coprocessor 1): 从 CP1 寄存器中读取值到通用寄存器中。CFC1(Move from Control Register 1): 从 CP1 的控制寄存器(如 FCSR)读取数据。CTC1(Move to Control Register 1): 将数据写入 CP1 的控制寄存器。
2 重要的 CP1 寄存器
2.1 单精度浮点寄存器
- 寄存器数量: 32 个,命名为
$f0到$f31。 - 数据类型: 每个
$f寄存器都是 32 位宽,用于存储一个单精度浮点数(遵循 IEEE 754 标准)。 - 特点:
- 可以作为独立的 32 位寄存器使用。
- 也可以配对形成 64 位双精度寄存器:
($f1, $f0)组成双精度寄存器$f0,($f3, $f2)组成$f2,依此类推。 - 注意:
$f0和$f1是一对,$f2和$f3是一对,以此类推,奇数编号的寄存器不能单独用于双精度运算。
2.2 双精度浮点寄存器
- 寄存器数量: 16 个,命名为
$f0到$f15(通过配对实现)。 - 数据类型: 每个
$f寄存器(在配对模式下)都是 64 位宽,用于存储一个双精度浮点数。 - 特点:
- 双精度指令(如
L.D,S.D,ADD.D)直接操作这些配对的寄存器。 add.d $f4, $f6, $f8指令会执行($f5, $f4) = ($f7, $f6) + ($f9, $f8)的运算。
- 双精度指令(如
2.3 浮点控制/状态寄存器
- FCSR (Floating-Point Control/Status Register): 这是一个 32 位的寄存器,用于控制浮点单元的行为和记录其状态。
- 状态部分:
- Cause: 记录浮点异常的原因(如溢出、除零、无效操作等)。
- Flags: 记录浮点比较的结果(如等于、小于、非零等)。
- 控制部分:
- Enable: 控制是否屏蔽特定的浮点异常。
- Mode: 设置舍入模式(如四舍五入、向零舍入等)。
- 状态部分:
3 CP1 代码示例
# 假设我们要计算 3.14 + 2.71 # 1. 将单精度浮点数加载到 f 寄存器 l.s $f0, 3.14 # 将 3.14 加载到 $f0 寄存器 l.s $f2, 2.71 # 将 2.71 加载到 $f2 寄存器 # 2. 执行单精度加法 add.s $f4, $f0, $f2 # 计算 $f0 + $f2,结果存入 $f4 # 3. 将结果存回内存 s.s $f4, result # 将 $f4 中的单精度结果存入内存的 result 位置 # ------------------- # 双精度运算示例 # 假设我们要计算 3.141592653589793 + 2.718281828459045 # 1. 将双精度浮点数加载到 f 寄存器对 l.d $f0, pi_64 # 将双精度 pi 加载到 ($f1, $f0) l.d $f2, e_64 # 将双精度 e 加载到 ($f3, $f2) # 2. 执行双精度加法 add.d $f4, $f0, $f2 # 计算 ($f1, $f0) + ($f3, $f2),结果存入 ($f5, $f4) # 3. 将结果存回内存 s.d $f4, result_64 # 将 ($f5, $f4) 中的双精度结果存入内存的 result_64 位置
| 特性 | 协处理器 0 (CP0) | 协处理器 1 (CP1) |
|---|---|---|
| 主要功能 | 系统控制(异常、中断、内存管理、MMU、缓存) | 浮点运算 |
| 寄存器类型 | 控制寄存器、状态寄存器、计数器等 | 单精度/双精度数据寄存器、控制/状态寄存器 |
| 访问指令 | mfc0, mtc0 |
mfc1, mtc1, cfc1, ctc1 |
| 关键寄存器 | Status, Cause, EPC, BadVAddr, Count, Compare |
$f0 - $f31 (单精度/双精度), FCSR |
| 重要性 | CPU 运行的基石,必须正确配置才能启动和运行 | 用于科学计算、图形学等需要浮点运算的场景 |
| 模式 | 通常在内核模式下访问和修改 | 可在用户模式下访问(如果系统允许) |
理解协处理器寄存器是掌握 MIPS 架构的关键,CP0 让 CPU 能够与硬件交互并响应系统事件,而 CP1 则极大地扩展了 CPU 的计算能力,使其能够处理复杂的科学和工程计算。
