asm-common-i386.h 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /* asm-common-i386.h - Common macros for i386 assembly
  2. *
  3. * Copyright (C) 2023 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_I386_H
  21. #define GCRY_ASM_COMMON_I386_H
  22. #include <config.h>
  23. #ifdef HAVE_COMPATIBLE_GCC_I386_PLATFORM_AS
  24. # define ELF(...) __VA_ARGS__
  25. #else
  26. # define ELF(...) /*_*/
  27. #endif
  28. #ifdef HAVE_COMPATIBLE_GCC_WIN32_PLATFORM_AS
  29. # define SECTION_RODATA .section .rdata
  30. #else
  31. # define SECTION_RODATA .section .rodata
  32. #endif
  33. #ifdef HAVE_COMPATIBLE_GCC_WIN32_PLATFORM_AS
  34. # define SYM_NAME(name) _##name
  35. #else
  36. # define SYM_NAME(name) name
  37. #endif
  38. #ifdef HAVE_COMPATIBLE_GCC_WIN32_PLATFORM_AS
  39. # define DECL_GET_PC_THUNK(reg)
  40. # define GET_DATA_POINTER(name, reg) leal name, %reg
  41. #else
  42. # define DECL_GET_PC_THUNK(reg) \
  43. .type __gcry_get_pc_thunk_##reg, @function; \
  44. .align 16; \
  45. __gcry_get_pc_thunk_##reg:; \
  46. CFI_STARTPROC(); \
  47. movl (%esp), %reg; \
  48. ret_spec_stop; \
  49. CFI_ENDPROC()
  50. # define GET_DATA_POINTER(name, reg) \
  51. call __gcry_get_pc_thunk_##reg; \
  52. addl $_GLOBAL_OFFSET_TABLE_, %reg; \
  53. movl name##@GOT(%reg), %reg;
  54. #endif
  55. #ifdef HAVE_GCC_ASM_CFI_DIRECTIVES
  56. /* CFI directives to emit DWARF stack unwinding information. */
  57. # define CFI_STARTPROC() .cfi_startproc
  58. # define CFI_ENDPROC() .cfi_endproc
  59. # define CFI_REMEMBER_STATE() .cfi_remember_state
  60. # define CFI_RESTORE_STATE() .cfi_restore_state
  61. # define CFI_ADJUST_CFA_OFFSET(off) .cfi_adjust_cfa_offset off
  62. # define CFI_REL_OFFSET(reg,off) .cfi_rel_offset reg, off
  63. # define CFI_DEF_CFA_REGISTER(reg) .cfi_def_cfa_register reg
  64. # define CFI_REGISTER(ro,rn) .cfi_register ro, rn
  65. # define CFI_RESTORE(reg) .cfi_restore reg
  66. # define CFI_PUSH(reg) \
  67. CFI_ADJUST_CFA_OFFSET(4); CFI_REL_OFFSET(reg, 0)
  68. # define CFI_POP(reg) \
  69. CFI_ADJUST_CFA_OFFSET(-4); CFI_RESTORE(reg)
  70. # define CFI_POP_TMP_REG() \
  71. CFI_ADJUST_CFA_OFFSET(-4);
  72. # define CFI_LEAVE() \
  73. CFI_ADJUST_CFA_OFFSET(-4); CFI_DEF_CFA_REGISTER(%esp)
  74. /* CFA expressions are used for pointing CFA and registers to
  75. * %rsp relative offsets. */
  76. # define DW_REGNO_eax 0
  77. # define DW_REGNO_edx 1
  78. # define DW_REGNO_ecx 2
  79. # define DW_REGNO_ebx 3
  80. # define DW_REGNO_esi 4
  81. # define DW_REGNO_edi 5
  82. # define DW_REGNO_ebp 6
  83. # define DW_REGNO_esp 7
  84. # define DW_REGNO(reg) DW_REGNO_ ## reg
  85. /* Fixed length encoding used for integers for now. */
  86. # define DW_SLEB128_7BIT(value) \
  87. 0x00|((value) & 0x7f)
  88. # define DW_SLEB128_28BIT(value) \
  89. 0x80|((value)&0x7f), \
  90. 0x80|(((value)>>7)&0x7f), \
  91. 0x80|(((value)>>14)&0x7f), \
  92. 0x00|(((value)>>21)&0x7f)
  93. # define CFI_CFA_ON_STACK(esp_offs,cfa_depth) \
  94. .cfi_escape \
  95. 0x0f, /* DW_CFA_def_cfa_expression */ \
  96. DW_SLEB128_7BIT(11), /* length */ \
  97. 0x77, /* DW_OP_breg7, rsp + constant */ \
  98. DW_SLEB128_28BIT(esp_offs), \
  99. 0x06, /* DW_OP_deref */ \
  100. 0x23, /* DW_OP_plus_constu */ \
  101. DW_SLEB128_28BIT((cfa_depth)+4)
  102. # define CFI_REG_ON_STACK(reg,esp_offs) \
  103. .cfi_escape \
  104. 0x10, /* DW_CFA_expression */ \
  105. DW_SLEB128_7BIT(DW_REGNO(reg)), \
  106. DW_SLEB128_7BIT(5), /* length */ \
  107. 0x77, /* DW_OP_breg7, rsp + constant */ \
  108. DW_SLEB128_28BIT(esp_offs)
  109. #else
  110. # define CFI_STARTPROC()
  111. # define CFI_ENDPROC()
  112. # define CFI_REMEMBER_STATE()
  113. # define CFI_RESTORE_STATE()
  114. # define CFI_ADJUST_CFA_OFFSET(off)
  115. # define CFI_REL_OFFSET(reg,off)
  116. # define CFI_DEF_CFA_REGISTER(reg)
  117. # define CFI_REGISTER(ro,rn)
  118. # define CFI_RESTORE(reg)
  119. # define CFI_PUSH(reg)
  120. # define CFI_POP(reg)
  121. # define CFI_POP_TMP_REG()
  122. # define CFI_LEAVE()
  123. # define CFI_CFA_ON_STACK(rsp_offs,cfa_depth)
  124. # define CFI_REG_ON_STACK(reg,rsp_offs)
  125. #endif
  126. /* 'ret' instruction replacement for straight-line speculation mitigation. */
  127. #define ret_spec_stop \
  128. ret; int3;
  129. /* This prevents speculative execution on old AVX512 CPUs, to prevent
  130. * speculative execution to AVX512 code. The vpopcntb instruction is
  131. * available on newer CPUs that do not suffer from significant frequency
  132. * drop when 512-bit vectors are utilized. */
  133. #define spec_stop_avx512 \
  134. vpxord %ymm7, %ymm7, %ymm7; \
  135. vpopcntb %xmm7, %xmm7; /* Supported only by newer AVX512 CPUs. */ \
  136. vpxord %ymm7, %ymm7, %ymm7;
  137. #define spec_stop_avx512_intel_syntax \
  138. vpxord ymm7, ymm7, ymm7; \
  139. vpopcntb xmm7, xmm7; /* Supported only by newer AVX512 CPUs. */ \
  140. vpxord ymm7, ymm7, ymm7;
  141. #endif /* GCRY_ASM_COMMON_AMD64_H */