asm-common-amd64.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. /* asm-common-amd64.h - Common macros for AMD64 assembly
  2. *
  3. * Copyright (C) 2018 Jussi Kivilinna <jussi.kivilinna@iki.fi>
  4. *
  5. * This file is part of Libgcrypt.
  6. *
  7. * Libgcrypt is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU Lesser General Public License as
  9. * published by the Free Software Foundation; either version 2.1 of
  10. * the License, or (at your option) any later version.
  11. *
  12. * Libgcrypt is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Lesser General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public
  18. * License along with this program; if not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #ifndef GCRY_ASM_COMMON_AMD64_H
  21. #define GCRY_ASM_COMMON_AMD64_H
  22. #include <config.h>
  23. #ifdef HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS
  24. # define ELF(...) __VA_ARGS__
  25. #else
  26. # define ELF(...) /*_*/
  27. #endif
  28. #ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
  29. # define SECTION_RODATA .section .rdata
  30. #else
  31. # define SECTION_RODATA .section .rodata
  32. #endif
  33. #ifdef __PIC__
  34. # define rRIP (%rip)
  35. #else
  36. # define rRIP
  37. #endif
  38. #ifdef __PIC__
  39. # define RIP %rip
  40. #else
  41. # define RIP
  42. #endif
  43. #ifdef __PIC__
  44. # define ADD_RIP +rip
  45. #else
  46. # define ADD_RIP
  47. #endif
  48. #if defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS) || !defined(__PIC__)
  49. # define GET_EXTERN_POINTER(name, reg) movabsq $name, reg
  50. #else
  51. # ifdef __code_model_large__
  52. # define GET_EXTERN_POINTER(name, reg) \
  53. pushq %r15; \
  54. pushq %r14; \
  55. 1: leaq 1b(%rip), reg; \
  56. movabsq $_GLOBAL_OFFSET_TABLE_-1b, %r14; \
  57. movabsq $name@GOT, %r15; \
  58. addq %r14, reg; \
  59. popq %r14; \
  60. movq (reg, %r15), reg; \
  61. popq %r15;
  62. # else
  63. # define GET_EXTERN_POINTER(name, reg) movq name@GOTPCREL(%rip), reg
  64. # endif
  65. #endif
  66. #ifdef HAVE_GCC_ASM_CFI_DIRECTIVES
  67. /* CFI directives to emit DWARF stack unwinding information. */
  68. # define CFI_STARTPROC() .cfi_startproc
  69. # define CFI_ENDPROC() .cfi_endproc
  70. # define CFI_REMEMBER_STATE() .cfi_remember_state
  71. # define CFI_RESTORE_STATE() .cfi_restore_state
  72. # define CFI_ADJUST_CFA_OFFSET(off) .cfi_adjust_cfa_offset off
  73. # define CFI_REL_OFFSET(reg,off) .cfi_rel_offset reg, off
  74. # define CFI_DEF_CFA_REGISTER(reg) .cfi_def_cfa_register reg
  75. # define CFI_REGISTER(ro,rn) .cfi_register ro, rn
  76. # define CFI_RESTORE(reg) .cfi_restore reg
  77. # define CFI_PUSH(reg) \
  78. CFI_ADJUST_CFA_OFFSET(8); CFI_REL_OFFSET(reg, 0)
  79. # define CFI_POP(reg) \
  80. CFI_ADJUST_CFA_OFFSET(-8); CFI_RESTORE(reg)
  81. # define CFI_POP_TMP_REG() \
  82. CFI_ADJUST_CFA_OFFSET(-8);
  83. # define CFI_LEAVE() \
  84. CFI_ADJUST_CFA_OFFSET(-8); CFI_DEF_CFA_REGISTER(%rsp)
  85. /* CFA expressions are used for pointing CFA and registers to
  86. * %rsp relative offsets. */
  87. # define DW_REGNO_rax 0
  88. # define DW_REGNO_rdx 1
  89. # define DW_REGNO_rcx 2
  90. # define DW_REGNO_rbx 3
  91. # define DW_REGNO_rsi 4
  92. # define DW_REGNO_rdi 5
  93. # define DW_REGNO_rbp 6
  94. # define DW_REGNO_rsp 7
  95. # define DW_REGNO_r8 8
  96. # define DW_REGNO_r9 9
  97. # define DW_REGNO_r10 10
  98. # define DW_REGNO_r11 11
  99. # define DW_REGNO_r12 12
  100. # define DW_REGNO_r13 13
  101. # define DW_REGNO_r14 14
  102. # define DW_REGNO_r15 15
  103. # define DW_REGNO(reg) DW_REGNO_ ## reg
  104. /* Fixed length encoding used for integers for now. */
  105. # define DW_SLEB128_7BIT(value) \
  106. 0x00|((value) & 0x7f)
  107. # define DW_SLEB128_28BIT(value) \
  108. 0x80|((value)&0x7f), \
  109. 0x80|(((value)>>7)&0x7f), \
  110. 0x80|(((value)>>14)&0x7f), \
  111. 0x00|(((value)>>21)&0x7f)
  112. # define CFI_CFA_ON_STACK(rsp_offs,cfa_depth) \
  113. .cfi_escape \
  114. 0x0f, /* DW_CFA_def_cfa_expression */ \
  115. DW_SLEB128_7BIT(11), /* length */ \
  116. 0x77, /* DW_OP_breg7, rsp + constant */ \
  117. DW_SLEB128_28BIT(rsp_offs), \
  118. 0x06, /* DW_OP_deref */ \
  119. 0x23, /* DW_OP_plus_constu */ \
  120. DW_SLEB128_28BIT((cfa_depth)+8)
  121. # define CFI_REG_ON_STACK(reg,rsp_offs) \
  122. .cfi_escape \
  123. 0x10, /* DW_CFA_expression */ \
  124. DW_SLEB128_7BIT(DW_REGNO(reg)), \
  125. DW_SLEB128_7BIT(5), /* length */ \
  126. 0x77, /* DW_OP_breg7, rsp + constant */ \
  127. DW_SLEB128_28BIT(rsp_offs)
  128. #else
  129. # define CFI_STARTPROC()
  130. # define CFI_ENDPROC()
  131. # define CFI_REMEMBER_STATE()
  132. # define CFI_RESTORE_STATE()
  133. # define CFI_ADJUST_CFA_OFFSET(off)
  134. # define CFI_REL_OFFSET(reg,off)
  135. # define CFI_DEF_CFA_REGISTER(reg)
  136. # define CFI_REGISTER(ro,rn)
  137. # define CFI_RESTORE(reg)
  138. # define CFI_PUSH(reg)
  139. # define CFI_POP(reg)
  140. # define CFI_POP_TMP_REG()
  141. # define CFI_LEAVE()
  142. # define CFI_CFA_ON_STACK(rsp_offs,cfa_depth)
  143. # define CFI_REG_ON_STACK(reg,rsp_offs)
  144. #endif
  145. #ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS
  146. # define ENTER_SYSV_FUNC_PARAMS_0_4 \
  147. pushq %rdi; \
  148. CFI_PUSH(%rdi); \
  149. pushq %rsi; \
  150. CFI_PUSH(%rsi); \
  151. movq %rcx, %rdi; \
  152. movq %rdx, %rsi; \
  153. movq %r8, %rdx; \
  154. movq %r9, %rcx; \
  155. # define ENTER_SYSV_FUNC_PARAMS_5 \
  156. ENTER_SYSV_FUNC_PARAMS_0_4; \
  157. movq 0x38(%rsp), %r8;
  158. # define ENTER_SYSV_FUNC_PARAMS_6 \
  159. ENTER_SYSV_FUNC_PARAMS_5; \
  160. movq 0x40(%rsp), %r9;
  161. # define EXIT_SYSV_FUNC \
  162. popq %rsi; \
  163. CFI_POP(%rsi); \
  164. popq %rdi; \
  165. CFI_POP(%rdi);
  166. #else
  167. # define ENTER_SYSV_FUNC_PARAMS_0_4
  168. # define ENTER_SYSV_FUNC_PARAMS_5
  169. # define ENTER_SYSV_FUNC_PARAMS_6
  170. # define EXIT_SYSV_FUNC
  171. #endif
  172. /* 'ret' instruction replacement for straight-line speculation mitigation. */
  173. #define ret_spec_stop \
  174. ret; int3;
  175. /* This prevents speculative execution on old AVX512 CPUs, to prevent
  176. * speculative execution to AVX512 code. The vpopcntb instruction is
  177. * available on newer CPUs that do not suffer from significant frequency
  178. * drop when 512-bit vectors are utilized. */
  179. #define spec_stop_avx512 \
  180. vpxord %ymm16, %ymm16, %ymm16; \
  181. vpopcntb %xmm16, %xmm16; /* Supported only by newer AVX512 CPUs. */ \
  182. vpxord %ymm16, %ymm16, %ymm16;
  183. #define spec_stop_avx512_intel_syntax \
  184. vpxord ymm16, ymm16, ymm16; \
  185. vpopcntb xmm16, xmm16; /* Supported only by newer AVX512 CPUs. */ \
  186. vpxord ymm16, ymm16, ymm16;
  187. #endif /* GCRY_ASM_COMMON_AMD64_H */