Why can’t MIPS use two registers in an addressing mode?

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.

Leave a Comment