Veneers have different capabilities and use different code pieces. The linker selects the most appropriate, smallest, and fastest depending on the branching requirements:
Performs only a state change.
The veneer must be inserted just before the target section to be in range.
An A32-T32 interworking veneer has a range of 256 bytes so the function entry point must appear within 256 bytes of the veneer.
A T32-A32 interworking veneer has a range of zero bytes so the function entry point must appear immediately after the veneer.
An inline veneer is always position-independent.
Short branch veneer:
An interworking T32 to A32 short branch veneer has a range of 32MB, the range for an A32 instruction.
A short branch veneer is always position-independent.
Long branch veneer:
Can branch anywhere in the 4GB address space.
All long branch veneers are also interworking veneers.
There are different long branch veneers for absolute or position-independent code.
When you are using veneers be aware of the following:
The inline veneer limitations mean that you cannot move inline veneers out of an execution region using a scatter file. Use the command-line option
--no_inlineveneerto prevent the generation of inline veneers.
All veneers cannot be collected into one input section because the resulting veneer input section might not be within range of other input sections. If the sections are not within addressing range, long branching is not possible.
The linker generates position-independent variants of the veneers automatically. However, because such veneers are larger than non position-independent variants, the linker only does this where necessary, that is, where the source and destination execution regions are both position-independent and are rigidly related.
Veneers are generated to optimize code size. armlink, therefore, chooses the variant in order of preference:
Short branch veneer.