Smart Branches

The 65816 branch instructions use an 8-bit offset, which gives them a range of -128 to +127. There is one exception – BRL – which has a 16-bit offset, so 16-bit conditional branches can be synthesized.

    bcs @farfaraway

becomes

    bcc *+5
    brl @farfaraway

But what’s a compiler writer to do? Blindly using an 8-bit branch will sometimes fail and blindly using a 16-bit branch wastes cycles and interferes with basic block analysis. Not to mention complex comparison (like less than or equal) which have to be composed of bcc and beq and signed comparison.

My solution was to ignore native branch instructions in favor of a synthetic smart branch. Like a real branch, it has a condition and a target. Unlike a real branch, it has a flag to indicate if it’s short or far and may expand to multiple bytes.

After most optimizations run, there is a pass to calculate the code size and determine if a far branch is needed. This is actually a multi-pass process since using a far branch increases the space used and could impact other branches in the code.

Then there is a final peephole pass to remove redundant CMP #0 instructions and the smart branch is expanded to real 65816 code.

The smart branches are: