跳转至内容

N64编程/CPU概述

来自Wikibooks,开放世界中的开放书籍
N64核心中的NEC VR4300。

处理器:93.75 MHz NEC VR4300,基于MIPS R4300i系列64位RISC CPU (信息)

寄存器

[编辑 | 编辑源代码]

32个通用寄存器,任天堂为其制定了命名约定。

R0 = 始终为零。任何修改此寄存器的尝试都会静默失败。
T0-T9 = 临时寄存器。CPU RAM。
S0-S7 = 函数协议保存的寄存器。如果您知道如何操作,可以随意使用。
A0-A3 = 传递给子程序的参数。正式但并不严格。
RA = 子程序的返回地址。不从“堆栈”中提取。可以根据需要更改。
V0-V1 = 算术值,函数返回值。
SP = 堆栈指针。非正式的。
AT = 汇编器临时寄存器。自由使用。

这些是正式定义,但除了R0是硬连线外,并没有严格执行。


指令为字大小(32位)。

协处理器

[编辑 | 编辑源代码]
RCP,也称为COP2。

除了CPU之外,还有三个其他协处理器。

  • COP0 = 存储器管理单元(MMU)。更广为人知的是“虚拟内存”。
  • COP1 = 浮点运算单元(FPU)。
  • COP2 = 视频协处理器(RCP)。

分支延迟

[编辑 | 编辑源代码]

执行分支时,会产生1个周期延迟。这意味着像beq r0,r0,8006D234h这样的分支指令也会执行其后的指令。延迟槽中可以放置的指令操作码是有限制的。

请注意,“beq r0,r0,TARGET”实际上是“bra TARGET”。


以下机器代码可以在马里奥高尔夫中找到。

[1120:0027] 800B0130: BEQ     t1[800FBBD0],r0[00000000],800B01D0h
[0000:0000] 800B0134: NOP

在从内存中获取下一条指令之前,执行NOP(无操作)。

[0c02:c0d7] 800B01B4: JAL     800B035C
[0120:2021] 800B01B8: ADDU    a0[00000038],t1[800FBBD0],r0[00000000]

当程序计数器设置为地址800B035C时,执行ADDU(无符号加法)。

出于我们的爱好者目的,始终在槽中低效地浪费一个NOP(无操作)并且在必要时进行优化,这样会更安全。

有符号加法

[编辑 | 编辑源代码]

使用MIPS指令的无符号系列时需要小心,因为符号性仅指指令是否会在溢出时生成陷阱。无论使用ADDI还是ADDIU,MIPS都会对操作数进行符号扩展。

LI $A0, 8013 ;A0 = 0x80130000
ADDIU $A0, $A0, FFFF ;A0 = 0x8012FFFF

基本上,即使使用无符号加法指令,当添加大于0x7FFF的值时,其效果就像该值为负数一样。这也影响相对寻址,例如:

LI $A0, 8013 ;A0 = 0x80130000
LW $A1, FFFF($A0) ;load word from 0x8012FFFF
华夏公益教科书