alternative-asm.h 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. #ifndef _ASM_ALTERNATIVE_ASM_H
  3. #define _ASM_ALTERNATIVE_ASM_H
  4. #ifdef __ASSEMBLER__
  5. #include <asm/asm.h>
  6. /*
  7. * Issue one struct alt_instr descriptor entry (need to put it into
  8. * the section .altinstructions, see below). This entry contains
  9. * enough information for the alternatives patching code to patch an
  10. * instruction. See apply_alternatives().
  11. */
  12. .macro altinstruction_entry orig alt feature orig_len alt_len
  13. .long \orig - .
  14. .long \alt - .
  15. .short \feature
  16. .byte \orig_len
  17. .byte \alt_len
  18. .endm
  19. /*
  20. * Define an alternative between two instructions. If @feature is
  21. * present, early code in apply_alternatives() replaces @oldinstr with
  22. * @newinstr. ".fill" directive takes care of proper instruction padding
  23. * in case @newinstr is longer than @oldinstr.
  24. */
  25. .macro ALTERNATIVE oldinstr, newinstr, feature
  26. 140 :
  27. \oldinstr
  28. 141 :
  29. .fill - (((144f-143f)-(141b-140b)) > 0) * ((144f-143f)-(141b-140b)) / 4, 4, 0x03400000
  30. 142 :
  31. .pushsection .altinstructions, "a"
  32. altinstruction_entry 140b, 143f, \feature, 142b-140b, 144f-143f
  33. .popsection
  34. .subsection 1
  35. 143 :
  36. \newinstr
  37. 144 :
  38. .previous
  39. .endm
  40. #define old_len (141b-140b)
  41. #define new_len1 (144f-143f)
  42. #define new_len2 (145f-144f)
  43. #define alt_max_short(a, b) ((a) ^ (((a) ^ (b)) & -(-((a) < (b)))))
  44. /*
  45. * Same as ALTERNATIVE macro above but for two alternatives. If CPU
  46. * has @feature1, it replaces @oldinstr with @newinstr1. If CPU has
  47. * @feature2, it replaces @oldinstr with @feature2.
  48. */
  49. .macro ALTERNATIVE_2 oldinstr, newinstr1, feature1, newinstr2, feature2
  50. 140 :
  51. \oldinstr
  52. 141 :
  53. .fill - ((alt_max_short(new_len1, new_len2) - (old_len)) > 0) * \
  54. (alt_max_short(new_len1, new_len2) - (old_len)) / 4, 4, 0x03400000
  55. 142 :
  56. .pushsection .altinstructions, "a"
  57. altinstruction_entry 140b, 143f, \feature1, 142b-140b, 144f-143f, 142b-141b
  58. altinstruction_entry 140b, 144f, \feature2, 142b-140b, 145f-144f, 142b-141b
  59. .popsection
  60. .subsection 1
  61. 143 :
  62. \newinstr1
  63. 144 :
  64. \newinstr2
  65. 145 :
  66. .previous
  67. .endm
  68. #endif /* __ASSEMBLER__ */
  69. #endif /* _ASM_ALTERNATIVE_ASM_H */