MARS 模拟器有 PC-relative 寻址是指字节数而不是字数?

MARS Simulator has PC-relative addressing refer to the number of bytes instead of words?

我目前正在阅读 David Patterson 和 John Hennesy 的书,标题为:"Computer Organisation and Design - 4th Edition"。在某些方面,这本书说:

Since all MIPS instructions are 4 bytes long, MIPS stretches the distance of the branch by having PC-relative addressing refer to the number of words to the next instruction instead of the number of bytes.

我一读到它,就去 MARS Simulator 看看它在实践中的表现。令我惊讶的是,我观察到 $pc 寄存器不遵循该规则并且始终存储字节内存地址。

$pc 寄存器在执行位于指令地址中的以下指令之前不应该是这样的吗?

Instruction Address |    $pc Content
                    |
    0x00400000      |     0x00100000
    0x00400004      |     0x00100001
    0x00400008      |     0x00100002
      ....          |         ....

换个角度看:PC的低2位固定为0

根据您的提议,高2位将固定为0jr $ra 或其他 jump-to-register 指令也必须 left-shift 寄存器而不是简单地设置 $pc = function-pointer.

(否则差异在体系结构上是可见的,并且必须将代码作为数据访问,反之亦然,以便从数据地址转换为同一字的代码地址。)


正如 Jester 指出的那样,$pc 是指向指令字的普通指针,就像 MIPS 用于处理 一样。 MIPS 使用 byte-addressable 内存,但字加载必须对齐(直到 MIPS32r6)。因此 $pc 每次使用时都会增加 4 而不是 缩放 4。

实际设计所需的唯一缩放比例是分支 (I-type) 和跳转 (J-type) 的立即数。请参阅 How to Calculate Jump Target Address and Branch Target Address? 了解其工作原理。这只是您将立即数位连接到加法器的哪个位置的问题,而将较低的位留为零。而且它只发生在这些指令的解码中;其他一切都只适用于普通字节地址。

... stretches the distance of the branch by having PC-relative addressing refer to the number of words to the next instruction instead of the number of bytes.

这句话只有的意思是:

地址X存储的指令0x1000nnnn(b nnnn)会跳转到地址X+4+4*nnnn的指令,不会跳转到地址[=12=的指令].

这句话没有提到 PC 寄存器及其值本身。

I observed that the $pc register doesn't follow that rule and has always the byte memory address stored.

Shouldn't the $pc register be something like this before the execution of the below instructions located in the instruction addresses?

这里的问题是:$pc寄存器到底是什么?

在某些 CPU(如 ARM)上,有一些指令可以用 MIPS 汇编语言写成 addu $t0,$t0,$pc。谈论这样的 CPU 很容易回答这个问题:

如果addu $t0,$t0,$pc指令被执行,$pc寄存器的值是将被添加到$t0的值。

在真正的 MIPS CPU(不是 MIPS 仿真器)上,PC 寄存器是某种内存(30 位锁存器),可以保存 30 位信息。

但是,当谈到存储在某些内存中的信息时,我们必须定义如何解释这些信息:

10000111 可以解释为 135(无符号)、87(BCD)、-121(二进制补码)、-120(一个补码)、-7(符号和绝对值)、SOME_ENUM_CONSTANT(枚举),-0.09、0.7、1.35(各种浮动和 fixed-point 变体)...

明确定义PC寄存器中的0000...011100位指向地址为0x70的指令。但是,如果这个值必须写成 PC=0x1CPC=0x70.

则没有定义

因此一些 MIPS 仿真器可能显示 $pc=0x400000 而另一个可能显示 $pc=0x100000 因为 PC 寄存器中的 相同 值!

不过,我认为(几乎)所有 MIPS 仿真器都会显示 $pc=0x400000,因为用户对指令指向的地址感兴趣。