什么是协处理器?

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

mips 协处理器寄存器详解
(图片来源网络,侵删)
  • 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) 指令。
  • 我们将重点讲解最常用和最重要的 CP0CP1

协处理器 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 工作流程示例:中断处理

  1. 中断发生:某个硬件(如定时器)发出中断信号。
  2. 硬件动作
    • CPU 检测到中断,并确认 Status 寄存器中的全局中断使能位 IE 为 1。
    • CPU 自动将当前的 PC(下一条指令地址)保存到 EPC 寄存器。
    • CPU 自动设置 Status 寄存器中的 EXL 位为 1,进入异常级别,屏蔽新的中断。
    • CPU 在 Cause 寄存器的 IP 字段中标记相应的中断源。
    • CPU 跳转到一个固定的内存地址(0x80000180 for MIPS I),该地址是异常入口点
  3. 软件处理
    • 异常处理程序开始执行。
    • 程序读取 Cause 寄存器,判断中断类型。
    • 如果是定时器中断,程序会处理定时器相关的任务。
    • 处理完毕后,程序执行 ERET (Exception Return) 指令。
  4. 恢复执行
    • 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 的计算能力,使其能够处理复杂的科学和工程计算。