使用寄存器作为偏移量 [英] Using a register as an offset

查看:402
本文介绍了使用寄存器作为偏移量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很好奇为什么我们不允许在MIPS中使用寄存器作为偏移量.我知道您不能将寄存器用作这样的偏移量:lw $t3, $t1($t4);我只是想知道为什么是这样.

这是硬件限制吗?还是仅仅是ISA的一部分?

解决方案

我很好奇为什么我们不允许在MIPS中使用寄存器作为偏移量.

我不确定您是说为什么MIPS程序集不允许您以这种形式编写它"还是为什么底层的ISA不提供这种形式".

如果是前者,那么答案是基本ISA没有任何提供该功能的机器指令,而且显然设计者们并没有决定提供任何在注释中,新的寻址模式在某些情况下随后添加了,尽管显然不是用于加载或存储的通用2-reg寻址模式.

这是硬件限制吗?还是仅仅是ISA的一部分?

那里有些二分法错误.从硬件可以当然支持这一意义上说,这当然不是硬件限制,即使在设计MIPS时也是如此.似乎暗示着某些现有硬件具有该限制,因此MIPS ISA以某种方式继承了它.我会怀疑这是另一回事:ISA是根据对硬件实现可能性的分析来定义的,然后由于不需要MIPS硬件,因此成为了硬件简化支持MIPS ISA之外的任何功能.


1 例如,支持需要从3个寄存器中读取的存储指令.

2 当然,值得问一下这样的伪指令是否是一个好主意:它可能会扩展为将两个寄存器加到一个临时寄存器中,然后再加上一个lw结果.始终存在将太多"工作隐藏起来的危险.由于这部分掩盖了将1:1映射到硬件负载的实际负载与在幕后进行额外算术的版本之间的差异,因此很容易想象这可能导致最佳决策.

以经典示例为例,该示例在循环中线性访问两个元素大小相等的数组.使用2寄存器寻址时,很自然地将此循环写为两个2寄存器访问(每个寄存器具有不同的基址寄存器和公共偏移寄存器).偏移量维护的唯一开销"是单个偏移量增量.这掩盖了这样一个事实,即内部需要两个隐藏的添加来支持寻址模式:直接增加每个基数而不使用偏移量会更好.此外,清除开销后,您可以看到展开循环并使用立即偏移量可以进一步减少开销.

I'm curious as to why we are not allowed to use registers as offsets in MIPS. I know that you can't use registers as offsets like this: lw $t3, $t1($t4); I'm just curious as to why that is the case.

Is it a hardware restriction? Or simply just part of the ISA?

解决方案

I'm curious as to why we are not allowed to use registers as offsets in MIPS.

I'm not sure if you mean "why does MIPS assembly not permit you to write it this form" or "why does the underlying ISA not offer this form".

If it's the former, then the answer is that the base ISA doesn't have any machine instructions that offers that functionality, and apparently the designers didn't decide to offer any pseudo-instruction that would implement that behind the scenes.2

If you're asking why the ISA doesn't offer it in the first place, it's just a design choice. By offering fewer or simpler addressing modes, you get the following advantages:

  • Less room is needed to encode a more limited set of possibilities, so you save encoding space for more opcodes, shorter instructions, etc.
  • The hardware can be simpler, or faster. For example, allowing two registers in address calculation may result in:
  • The need for an additional read port in the register file1.
  • Additional connections between the register file and the AGU to get both registers values there.
  • The need to do a full width (32 or 64 bit) addition rather than a simpler address-side + 16 bit-addition for the offset.
  • The need to have a three-input ALU if you want to still want to support immediate offsets with the 2-register addresses (and they are less useful if you don't).
  • Additional complexity in instruction decoding and address-generation since you may need to support two quite different paths for address generation.

Of course, all of those trade-offs may very well pay off in some contexts that could make good use of 2-reg addressing with smaller or faster code, but the original design which was heavily inspired by the RISC philosophy didn't include it. As Peter points out in the comments, new addressing modes have been subsequently added for some cases, although apparently not a general 2-reg addressing mode for load or store.

Is it a hardware restriction? Or simply just part of the ISA?

There's a bit of a false dichotomy there. Certainly it's not a hardware restriction in the sense that hardware could certainly support this, even when MIPS was designed. It sort of seems to imply that some existing hardware had that restriction and so the MIPS ISA somehow inherited it. I would suspect it was much the other way around: the ISA was defined this way, based on analysis of how likely hardware would be implemented, and then it became a hardware simplification since MIPS hardware doesn't need to support anything outside of what's in the MIPS ISA.


1 E.g., to support store instructions which would need to read from 3 registers.

2 It's certainly worth asking whether such a pseudo-instruction is a good idea or not: it would probably expand to an add of the two registers to a temporary register and then a lw with the result. There is always a danger that this hides "too much" work. Since this partly glosses over the difference between a true load that maps 1:1 to a hardware load, and the version that is doing extra arithmetic behind the covers, it is easy to imagine it might lead to sup-optimal decisions.

Take the classic example of linearly accessing two arrays of equal element size in a loop. With 2-reg addressing, it is natural to write this loop as two 2-reg accesses (each with a different base register and a common offset register). The only "overhead" for the offset maintenance is the single offset increment. This hides the fact that internally there are two hidden adds required to support the addressing mode: it would have simply been better to increment each base directly and not use the offset. Furthermore, once the overhead is clear, you can see that unrolling the loop and using immediate offsets can further reduce the overhead.

这篇关于使用寄存器作为偏移量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆