我很好奇为什么我们不允许在MIPS中使用寄存器作为偏移量。我知道你 * 不能 * 像这样使用寄存器作为偏移量:我只是好奇为什么会这样。
这是硬件限制吗?还是只是伊萨的一部分?
PS:如果您正在寻找替代方法,请参见 * Load Word in MIPS, using register instead of immediate offset from another register * 或查看编译器输出的C函数,如int foo(int *arr, int idx){ return arr[idx]; }
-https://godbolt.org/z/PhxG57ox1
1条答案
按热度按时间k2arahey1#
我很好奇为什么不允许我们在MIPS中使用寄存器作为偏移量。
我不确定您的意思是“为什么MIPS程序集不允许您以这种形式编写它”还是“为什么底层伊萨不提供这种形式”。
如果是前者,那么答案是基本伊萨没有任何机器指令提供该功能,显然设计者没有决定提供任何pseudo-instruction来在幕后实现该功能。2
如果您问伊萨为什么不提供这种寻址模式,那只是一种设计选择。通过提供更少或更简单的寻址模式,您可以获得以下优势:
当然,在某些情况下,所有这些权衡可能会得到很好的回报,可以很好地利用2-reg寻址和更小或更快的代码,但最初的设计,这是在RISC哲学的重大启发没有包括它。正如Peter在评论中指出,新的寻址模式 * 已经 * 随后被添加到某些情况下,虽然显然不是用于加载或存储的一般2-reg寻址模式。
这是硬件限制吗?还是只是伊萨的一部分?
这里有一点错误的二分法。当然,这不是一个硬件限制,因为硬件 * 肯定 * 可以支持这一点,即使在MIPS被设计的时候。这似乎暗示了一些现有的硬件有这个限制,所以MIPS伊萨以某种方式继承了它。我会怀疑它是相反的:伊萨是这样定义的,它基于对硬件实现可能性的分析,然后它变成了一种 * 硬件简化 *,因为MIPS硬件不需要支持MIPS ISA之外的任何东西。
1例如,支持需要从3个寄存器读取的存储指令。
[2]这样的伪指令是否是一个好主意,当然值得一问:它可能会扩展为将两个寄存器加到一个临时寄存器上,然后用
lw
来计算结果。这样做总是有隐藏“太多”工作的危险。由于这部分掩盖了1:1Map到硬件负载的真实负载和在掩盖后进行额外运算的版本之间的差异,很容易想象它可能会导致次优决策。以在循环中线性访问两个元素大小相等的数组为例。对于2-reg寻址,很自然地将此循环写为两次2-reg访问(每一次访问都有不同的基址寄存器和公共的偏移量寄存器)。偏移量维护的唯一“开销”是单个偏移量增量。这隐藏了一个事实,即内部有两个隐藏的加法需要支持寻址模式:直接递增每个基址而不使用偏移量会更好。此外,一旦开销被清除,您可以看到展开循环并使用立即数偏移量可以进一步减少开销。