5

I am statically reversing some software compiled for an Atheros AR7161 using radare2. This processor implements MIPS, and I do recall that MIPS has a branch delay slot. This is indeed noticeable in the disassembly because I can see instructions that should logically execute before branches being placed right after them.

However, while analyzing some piece of code, I came across a beqz instruction for which assuming that the instruction after it should execute first does not make sense in the context of the program. I must admit that my analysis could be wrong, which is not unlikely; however, I have some doubts that I'd also like to clear:

  • Do all branch/jump instructions always use the branch delay slot such that the instruction right after should logically execute first? If not, in which cases would it not?

  • Is there some way to make radare2 show the logical execution order rather than the one encoded in the binary?

Edit: concretely, I am dealing with the following sequence:

beqz v0, <some address>
lb v0, 0x40(sp)

I have a very diffuse picture in my head about these instruction going into the pipeline. I can picture the second instruction being fetched while the first one is being decoded; hence, execution of the branch delay slot should actually start. However, the branch instruction depends on the same register being modified by the instruction in the branch delay slot, so what will happen? Will the branch instruction evaluate the condition using the old register value, or the new one updated by lb?

Thanks

  • 2
    You might benefit from reading the MIPS series by Raymond Chen here: link The first answer is no (and see the link for details). I can't answer the second. – peter ferrie Oct 12 '18 at 17:13
5

The instruction in the branch delay slot is evaluated after the branch (or jump) instruction. The execution of the instruction in the branch delay slot does not impact the evaluation of the branch condition.

I have observed the branch delay slot be used for a few things:

  • Last instruction of basic block leading up to the branch instruction
    • Branch test will not be dependent on the output of the calculation of the branch delay slot instruction
    • Commonly seen with unconditional jumps/branches like b, jal
  • The first instruction of the the fall through block.
    • No side effects should be present if the branch is taken.
    • Analysis will show that any registers impacted is not needed in the event the branch is taken
  • The first instruction of block if the branch is taken
    • If there are multiple paths to the branch target, this instruction will likely be seen multiple times with the different branches
  • The load of a conditional value, often for return values

This article goes into detail about branch delay slots.

As noted by Igor, the "likely" version of the branch instruction keeps the effects of the instruction in the branch delay slot only if the instruction is actually taken.

3
  1. There are variations of conditional branches called "branch [ on condition] likely", e.g.
    • bgezl - Branch on Greater Than or Equal to Zero Likely
    • beql - Branch on Equal Likely

These instructions have a delay slot but the instruction in the delay slot is executed only if the branch is taken. If the branch is not taken, the instruction in the delay slot is not executed (nullified).

NB: these instructions have been removed in the Release 6 of MIPS Architecture. It also added compact variations of branches which do not have delay slots

As for your snippet, I strongly suspect that the branch uses the old register value, but you can probably confirm it only by running it on an actual processor.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.