# MIPS Architecture : PC-relative addressing

In case of branch Instructions such as beq, bne, we use PC-relative addressing. But I am really not clear why it is said in most of the books that MIPS address(while calculating branch target) is actually relative to the address of following instruction PC+4 as opposed to the current instruction PC?

• Probably by the time the relative address is used, PC has advanced beyond the branch instruction itself, due to pipelining. Feb 13 '14 at 15:53
• Will it be the same case if branch prediction technique such as 'branch taken' is applied? Feb 13 '14 at 16:13
• The semantics will be the same. As a programmer, you should not worry about how the CPU implements its instructions, unless you worry about efficiency. Feb 13 '14 at 16:14
• Yeah but, I am interested in knowing the internal implementation as well. Well, one more doubt- If calculating the relative address cannot be accomplished in same clock cycle as it involves ALU(And you just pointed out in your first comment), but few other architectures provide fast comparator (instead of involving ALU) to predict if the branch should be taken or not. So in that case this condition won't be valid? Am I right? Feb 13 '14 at 16:25
• The condition could be there for historical reasons. Modern processors are probably "smarter" than earlier ones. Regarding implementation, I have no idea. That's a separate question. Feb 13 '14 at 20:19

Branch instructions in MIPS have a 16-bit offset value which is sign-extended to provide offsets between -32768 and 32767 words (-131072 and 131068 bytes). This offset is added to the Next PC value rather than the PC of the branch itself.

Why the NPC is used rather than the PC of the branch is not obvious (to me). This may have been related to the use in the Stanford MIPS project of an assembler which performed the limited instruction reordering for filling the delayed branch slot with a previous instruction. With such a design, the offset for forward branches (i.e., branches with positive offsets, commonly used to implement if-then, conditionally branching over the then clause) would never be changed during the conversion and the offset for backward branches (i.e., branches with negative offsets, commonly used for loops) would only be changed when the delay slot had to be filled with an extra no-op instruction. This might simplify compiler development.

An alternative speculation would be that such slightly simplified the initial implementation where the branch was evaluated in the second pipeline stage when the current PC is the NPC relative to the branch instruction.

A third speculation is that such was considered conceptually cleaner given the use of a delayed branch slot. The offset then becomes relative to the instruction in which the branch is "activated".

• I am little confused. Will you please explain in short the concept of forward & backward branches? Feb 13 '14 at 16:10
• @user1612078 Did the edit clarify forward and backward branches? Feb 13 '14 at 19:05
• @ Paul A. Clayton : Yeah now understood properly. Thanks. Well, one more doubt- If calculating the relative address cannot be accomplished in same clock cycle as it involves ALU, but few other architectures provide fast comparator (instead of involving ALU) to predict if the branch should be taken or not & that too in same clock cycle. So in that case this condition(i.e branch target relative to PC+4) wouldn't be valid? Am I right? Feb 14 '14 at 18:44
• @user1612078 I receive the impression that using PC+4 is a relatively arbitrary choice. I think it would not be important so much when in the pipeline the condition is evaluated as when the target is calculated. If the target is calculated in the second stage, it might be slightly convenient to take the PC+4 value directly from the fetch control. If the target is calculated later (e.g., in the execute stage using the general ALU), then using the address of the instruction may be more convenient since it might be carried along with the instruction to simplify exception handling. Feb 15 '14 at 18:11

As the comments say, it was probably easier to fit the "add the displacement to the target" in after the "increment PC" (sub)step of instruction execution (that one is done very early).

This won't make much of a difference, just that the reach "forward" is somewhat greater than "backwards," and that might affect some corner cases. In any case, I've met assemblers(!) which implemented too long branch on equal (be target) as:

          bne continue
jmp target
continue: ...
.
.
.
target:   ...