Expand/Shrink

ARM branches

Opcode 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10  9  8  7  6  5  4  3  2  1  0
O8 RN RD RS OPC2 RM
COND OOOO OFFSET
bx[cond] Rm (aka ret) cond 0 0 0 1 0 0 1 0 SBO SBO SBO 0 0 0 1 Rm
b[cond] <target addr> (aka jmp) cond 1 0 1 0 24_bit_offset
bl[cond] <target addr> (aka call) cond 1 0 1 1 24_bit_offset

The bx lr instruction is most like and aliased to the x86 ret (no imm) instruction.
The b instruction is most like and aliased to the x86 jmp label instruction (32MB limit).
The bl instruction is most like and aliased to the x86 call label instruction (32MB limit).
A mov lr,pc; b Rm; pair should (manually/explicitly) be used instead of an x86 call register instruction.
Note that since call/return on the ARM uses the lr (link register) instead of the system stack,
there is no equivalent form of the x86 ret imm instruction, however you can of course use
add sp,NN; pop {pc} or perhaps better yet pop {Rm-Rn,pc} to mimic it.
It is also quite common to see lr being popped followed by a bx lr, which is perhaps understandable for manually written code,
but I can think of no good reason for a compiler to follow suit, given that the lr bit is adjacent to the pc bit, so it’s
not like other register restores c/would run interference, and it should instead pop pc directly rather than into lr and jumping,
and obviously that way emit one less instruction.


Note that eg #ilASM{call "libc", "printf"} has to jump through several hoops: a couple of symtab entries, an entry in the string table, a relocation entry, and a ".word printf" near the start of the data section [fetchable via ip], as well as emitting the three instructions "ldr rN, [ip+imm]; mov lr, pc; bx rN;". (At a bare minimum and at this stage that’s all a bit of a guess!)

There is no (deliberate) support for entering thumb mode via bx, that is, in Phix, which
should not be surprising since there is (as yet) no way to generate any thumb instructions.

The blx instruction is not supported, if necessary replace eg "blx r4" with "mov lr,pc" and "bx r4".

Phix Traditional branches Sometimes Better
function gcd(integer a,b)
    while a!=b do
        if a>b then
            a -= b
        else
            b -= a
        end if
    end while
    return a
end function
    gcd:    cmp r0,r1    
            beq stop
            blt less
            sub r0,r1
            b gcd
    less:
            sub r1,r0
            b gcd
    stop:
            bx lr
 
    gcd:    cmp r0,r1
            subgt r0,r1    
            sublt r1,r0
            bne gcd
            bx lr
 

The cut-off point for sticking with traditional branches over unconditional instructions is quite small: typically 4..6 instructions, so I’m told.