Bug Hunter's Cookbook

written by missing

Part 6: Jumps and Branches

The CPU will execute instructions in sequential order from top to bottom. This is good for simple programs but what if we want to do more than just add two numbers? For more complex programs, we may need loops or other conditions and these are accomplished through jumps and branches.

What is a branch?

A branch is like walking and reaching a fork in the road. There are two paths from where you are standing and depending on which path you choose, you will go somewhere else.

When disassembling a program and viewing the graph mode, a typical representation of a branch may look like this:

The fork in the road is where the end of the first block occurs where there is a green arrow and a red arrow leading to separate blocks of code. The green path will be taken if the branch condition is true and the red path will be taken if the branch condition is false.

In this example, bnez $v0, 0x814, if $v0 does NOT contain the number 0, then the code will take the green path and otherwise take the red path.

Branch Delay Slot

Branching seems simple enough; however, in MIPS implementation it is a little bit more nuanced.

When the processor executes an instruction, the program counter is advanced during the Instruction Fetch (IF) stage.

Due to the pipeline structure where when a jump or branch is being executed and the instruction afterwards would also be put into the pipeline, MIPS implements something called the branch delay slot.

Control hazards occur because the $pc after a branch is not known until it is figured out if the branch should be taken or not.

Instead of throwing the next instruction away when taking the branch, the instruction that is directly below a branch or jump always runs whether the branch is taken or not. This is why the instruction position after a branch or jump is called the branch delay slot.

As mentioned before, $pc is modified by 4 after the instruction fetch stage; however, when the branch is taken, $pc is modified during the branch instruction's execution (EX) stage. This affects what is chosen to be the next instruction after the branch delay slot that will be brought into the pipeline.

For the following instructions:

            0x7e4  lw $v0, 0x18($fp)
            0x7e8  bnez $v0, 0x814
            0x7ec  noop                            # branch delay slot
            0x7f0  lw $v0, -0x7fd0($gp)            # branch NOT taken
            0x7f4  addiu $a0, $v0, str.x_is_0
            ...
            0x814  lw $v0, -0x7fd0($gp)            # branch taken
            0x818  addiu $a0, $v0, str.x_is_NOT_0
            

If the branch is taken, lw $v0, -0x7fd0($gp) from address 0x814 will be put into the pipeline.

$pc Cycles 1 2 3 4 5 6 7 8 9
0x7e4 lw $v0, 0x18($fp) IF ID EX ME WB
0x7e8 bnez $v0, 0x814 IF ID EX ME WB
0x7ec noop IF ID EX ME WB
0x814   lw $v0, -0x7fd0($gp) IF ID EX ME WB
0x818 addiu $a0, $v0, str.x_is_NOT_0 IF ID EX ME WB

If the branch is NOT taken, $pc has not been modified by the branch instruction's execution stage, so the instruction from address 0x7f0 will be in the pipeline:

$pc Cycles 1 2 3 4 5 6 7 8 9
0x7e4 lw $v0, 0x18($fp) IF ID EX ME WB
0x7e8 bnez $v0, 0x814 IF ID EX ME WB
0x7ec   noop IF ID EX ME WB
0x7f0 lw $v0, -0x7fd0($gp) IF ID EX ME WB
0x7f4 addiu $a0, $v0, str.x_is_0 IF ID EX ME WB

Note: When no work is to be performed upon branching, often a noop is placed in the branch delay slot.

So what is a jump?

Jumps and branches both modify the program counter ($pc) in order to change code flow of the program and both utilize the branch delay slot; however, they are different based on how they modify the program counter.

Branches are conditional and are used to provide logic to the program and make it do different things. Branches require several bits in the machine code instruction for the condition so they have less bits to use for the location of the branch. That's why branches use a specified offset from the current program counter and can't go as far as a jump.

Jumps are unconditional and have more bits to go to a specified 26-bit memory address.

In short, jumps can go to code that is a greater distance in memory using an absolute address whereas branches have a shorter range and are relative because they are conditional.

Further Reading

1. Branch Delay Slot Tricks

2. Delay Slot [ Wikipedia ]

2. Branch Prediction Schemes (IA State)

Part 7: Calling Conventions