insn.h 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef __ASM_ARM_INSN_H
  3. #define __ASM_ARM_INSN_H
  4. #include <linux/types.h>
  5. /*
  6. * Avoid a literal load by emitting a sequence of ADD/LDR instructions with the
  7. * appropriate relocations. The combined sequence has a range of -/+ 256 MiB,
  8. * which should be sufficient for the core kernel as well as modules loaded
  9. * into the module region. (Not supported by LLD before release 14)
  10. */
  11. #define LOAD_SYM_ARMV6(reg, sym) \
  12. " .globl " #sym " \n\t" \
  13. " .reloc 10f, R_ARM_ALU_PC_G0_NC, " #sym " \n\t" \
  14. " .reloc 11f, R_ARM_ALU_PC_G1_NC, " #sym " \n\t" \
  15. " .reloc 12f, R_ARM_LDR_PC_G2, " #sym " \n\t" \
  16. "10: sub " #reg ", pc, #8 \n\t" \
  17. "11: sub " #reg ", " #reg ", #4 \n\t" \
  18. "12: ldr " #reg ", [" #reg ", #0] \n\t"
  19. static inline unsigned long
  20. arm_gen_nop(void)
  21. {
  22. #ifdef CONFIG_THUMB2_KERNEL
  23. return 0xf3af8000; /* nop.w */
  24. #else
  25. return 0xe1a00000; /* mov r0, r0 */
  26. #endif
  27. }
  28. unsigned long
  29. __arm_gen_branch(unsigned long pc, unsigned long addr, bool link, bool warn);
  30. static inline unsigned long
  31. arm_gen_branch(unsigned long pc, unsigned long addr)
  32. {
  33. return __arm_gen_branch(pc, addr, false, true);
  34. }
  35. static inline unsigned long
  36. arm_gen_branch_link(unsigned long pc, unsigned long addr, bool warn)
  37. {
  38. return __arm_gen_branch(pc, addr, true, warn);
  39. }
  40. #endif