-1

In MIPS, to calculate the address of the new instruction in the case of branches, the offsets (shifted 16 bits) are added to the current PC. but to calculate the address of the new instruction in case of jumps, the current PC is replaced with the new 26 bits from the jump. what is the logic behind replacing the whole value of the PC with the new value? why we just do the same as we calculate the new address in the case of branches?

Detailed of how the Jump Target Address and Branch Target Address is calculated is in this link How to Calculate Jump Target Address and Branch Target Address?

Mohamed
  • 129
  • 6
  • The idea is that you break up the address into 16 256MB "zones". You can use J to jump freely within any zone. 256MB was plenty of space, given that computers at the time the MIPS was released came with 1MB of memory. Even today, a single module is unlikely to come close to 256MB in size. – Raymond Chen Dec 31 '20 at 02:07
  • 1
    @RaymondChen, typo: the 6 bits copied from the PC gives it 64 256MB zones. – Erik Eidt Dec 31 '20 at 15:27
  • @ErikEidt 26 bits from the instruction, 2 bits are always zero, and 4 bits come from the PC. (Alternate math: 4GB / 256MB = 16.) – Raymond Chen Dec 31 '20 at 16:52
  • @RaymondChen Oops, thanks! – Erik Eidt Dec 31 '20 at 16:55

1 Answers1

1

The motivation appears as follows:

A pc-relative branch with 26 bits can reach +/- 128MB, which is a 256MB range.  For code in the middle of a code segment, it can reach anywhere in that range.  However, code that is near either the beginning or end can only reach 128MB of that code segment — the code at the beginning can reach +128MB and the code near the end can reach -128MB and so for them half the reach is "wasted".  Thus, the maximum code segment without concern or mitigation is 128MB.

By using a more absolute notion, all code — whether near the beginning, middle, or end of a code segment can reach a full 256MB range.


The downside to this approach is that code segments effectively need to begin on 256MB boundaries (i.e. without severely complicating linking), limiting the count of code segments to 16 in total.

Using a large pc-relative displacement instead would limit the size of a code segment to ~128MB, which is still huge, and, would have removed the code segment count limitation, since all code would be pc-relative.

RISC V has done away with this approach in favor of pc-relative addressing — though the largest displacement in 1 instruction is smaller at 21 bits, meaning the 1-instruction call model may fail when the code segment is larger than 1MB; the next model uses 2 instructions (AUIPC & JALR) to perform pc-relative branching/calling with a 32-bit range (i.e. +/-2GB).

The RISC V toolchain also supports "Relaxation", which means that the linker can shorten multiple instruction branch or data reference sequences when the actual displacement allows (making the compiler put out fixups even for internal branches and label deltas, since the generated code's size may change internally!).


I'll see if I can find some reference, though the logic seems to make sense.


From "MIPS® Architecture For Programmers Volume II-A: The MIPS32® Instruction Set, Revision 5.04", on Page 142 (J instruction; p. 143 JAL instruction).

Programming Notes:
Forming the branch target address by catenating PC and index bits rather than adding a signed offset to the PC is an advantage if all program code addresses fit into a 256MB region aligned on a 256MB boundary. It allows a branch from anywhere in the region to anywhere in the region, an action not allowed by a signed relative offset.

Erik Eidt
  • 23,049
  • 2
  • 29
  • 53