# ARM branches

|Opcode..................................|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|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.