12

After reading the question I'm still not sure how CPU does branching.

I understand that we have an instruction counter which points to the current instruction. And after performing conditional jump it either stays the same (increments as usual) or increases (jumps) and points to another branch, that's clear.

The problem: to define conditional jump we need a conditional jump? I mean in order to evaluate an IF the processor has to evaluate condition and IF it's true, then jump, otherwise not. It's an endless recursion.

So how does the conditional jump work on the lowest level?

LNK
  • 239
  • 2
  • 5

2 Answers2

29

The problem: to define conditional jump we need a conditional jump? I mean in order to evaluate an IF the processor has to evaluate condition and IF it's true, then jump, otherwise not. It's an endless recursion.

Processors have some level of code that is directly executed, by hardware circuits. That might not be the same level that they expose as their ISA, processors may translate ISA-level instructions into some other form before really executing them or even treat ISA-level instructions as small subroutines that are implemented in micro-code, but there is still some level is not interpreted in terms of something else and built into the physical structure of the hardware.

Below is a diagram of a simple processor. The "if" in the logic of "if we need to branch then take PC+offset as next PC, otherwise take PC+4" is implemented by the top left multiplexer (labeled Mux). A multiplexer does not actually "do one thing or the other", it combines two signals and a control signal via the formula: (~condition & a) | (condition & b). That's just a boolean formula that can be implemented easily as a physical circuit.

diagram

user555045
  • 2,148
  • 14
  • 15
7

The problem: to define conditional jump we need a conditional jump? I mean in order to evaluate an IF the processor has to evaluate condition and IF it's true, then jump, otherwise not. It's an endless recursion.

We can define a conditional jump in terms of a conditional move. For example, a conditional jump can be:

  1. Increment the program counter to point to the next instruction.
  2. Test the condition.
  3. Conditionally load the program counter with the jump target if the condition tested true in step 2.
  4. Go to the instruction the program counter refers to.

Notice that step 3 is executed unconditionally. It is a conditional move, but we always execute the conditional move. No jump capability of any kind is required here.

So conditional jumps are built out of conditional moves which are not implemented using any kind of jump at all. The conditional move always takes place, it just doesn't always have the semantic affect of moving anything.

It is important to understand that conditional moves can be built out of unconditional moves. If we do some math that results in the value we unconditionally move being the same as the previous value we are moving on top of, the effect is the same as if the move never occurred. So we can build the semantic effect of a conditional move entirely out of unconditional code.

Here's an example of a way to implement a conditional move that doesn't involve any conditions:

  1. Multiply the current value of the program counter by the condition.
  2. Invert the condition.
  3. Multiply the current value of the jump target by the condition.
  4. Add the result of step 3 to the program counter.

You can see that this leaves the value of the program counter unchanged if the condition is zero and loads the program counter with the jump target if the condition is one. This code is a straight-through flow with no conditional code at all.

Because a conditional move can easily be built out of unconditional operations, reducing a conditional branch to a conditional move is sufficient to implement conditional branches.

David Schwartz
  • 211
  • 1
  • 5