@@ -624,4 +624,41 @@ THUMB( orr \reg , \reg , #PSR_T_BIT )
.endif
.endm
+ /*
+ * bl_r - branch and link to register
+ *
+ * @dst: target to branch to
+ * @c: conditional opcode suffix
+ */
+ .macro bl_r, dst:req, c
+ .if __LINUX_ARM_ARCH__ < 6
+ mov\c lr, pc
+ mov\c pc, \dst
+ .else
+ blx\c \dst
+ .endif
+ .endm
+
+ /*
+ * bl_m - branch and link to address held in memory
+ *
+ * @dst: memory reference to load the branch target from
+ *
+ * This uses the same syntax as ldr instructions, including things like
+ * register writeback (where it makes sense). For example,
+ *
+ * bl_m [ip, #<offset>]
+ *
+ * Note that @dst should not reference lr as it may be clobbered early.
+ */
+ .macro bl_m, dst:vararg
+ .if __LINUX_ARM_ARCH__ < 6
+ mov lr, pc
+ ldr pc, \dst
+ .else
+ ldr lr, \dst
+ blx lr
+ .endif
+ .endm
+
#endif /* __ASM_ASSEMBLER_H__ */
Add some macros that abstract the difference between the ways indirect calls are performed on older and newer ARM architecture revisions. The main difference is to prefer blx instructions over explicit LR assignments when possible, as these tend to confuse the prediction logic in out-of-order cores when speculating across a function return. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> --- arch/arm/include/asm/assembler.h | 37 ++++++++++++++++++++ 1 file changed, 37 insertions(+)