fat_entry.asm
上传用户:qaz666999
上传日期:2022-08-06
资源大小:2570k
文件大小:4k
源码类别:

数学计算

开发平台:

Unix_Linux

  1. dnl  x86 fat binary entrypoints.
  2. dnl  Contributed to the GNU project by Kevin Ryde (original x86_32 code) and
  3. dnl  Torbjorn Granlund (port to x86_64)
  4. dnl  Copyright 2003, 2009 Free Software Foundation, Inc.
  5. dnl
  6. dnl  This file is part of the GNU MP Library.
  7. dnl
  8. dnl  The GNU MP Library is free software; you can redistribute it and/or
  9. dnl  modify it under the terms of the GNU Lesser General Public License as
  10. dnl  published by the Free Software Foundation; either version 3 of the
  11. dnl  License, or (at your option) any later version.
  12. dnl
  13. dnl  The GNU MP Library is distributed in the hope that it will be useful,
  14. dnl  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. dnl  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16. dnl  Lesser General Public License for more details.
  17. dnl
  18. dnl  You should have received a copy of the GNU Lesser General Public License
  19. dnl  along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.
  20. include(`../config.m4')
  21. dnl  Forcibly disable profiling.
  22. dnl
  23. dnl  The entrypoints and inits are small enough not to worry about, the real
  24. dnl  routines arrived at will have any profiling.  Also, the way the code
  25. dnl  here ends with a jump means we won't work properly with the
  26. dnl  "instrument" profiling scheme anyway.
  27. define(`WANT_PROFILING',no)
  28. TEXT
  29. dnl  Usage: FAT_ENTRY(name, offset)
  30. dnl
  31. dnl  Emit a fat binary entrypoint function of the given name.  This is the
  32. dnl  normal entry for applications, eg. __gmpn_add_n.
  33. dnl
  34. dnl  The code simply jumps through the function pointer in __gmpn_cpuvec at
  35. dnl  the given "offset" (in bytes).
  36. dnl
  37. dnl  For non-PIC, the jumps are 5 bytes each, aligning them to 8 should be
  38. dnl  fine for all x86s.
  39. dnl
  40. dnl  For PIC, the jumps are 20 bytes each, and are best aligned to 16 to
  41. dnl  ensure at least the first two instructions don't cross a cache line
  42. dnl  boundary.
  43. dnl
  44. dnl  Note the extra `' ahead of PROLOGUE obscures it from the HAVE_NATIVE
  45. dnl  grepping in configure, stopping that code trying to eval something with
  46. dnl  $1 in it.
  47. define(FAT_ENTRY,
  48. m4_assert_numargs(2)
  49. ` ALIGN(ifdef(`PIC',16,8))
  50. `'PROLOGUE($1)
  51. ifdef(`PIC',
  52. ` LEA( GSYM_PREFIX`'__gmpn_cpuvec, %rax)
  53. jmp *$2(%rax)
  54. ',`dnl non-PIC
  55. jmp *GSYM_PREFIX`'__gmpn_cpuvec+$2
  56. ')
  57. EPILOGUE()
  58. ')
  59. dnl  FAT_ENTRY for each CPUVEC_FUNCS_LIST
  60. dnl
  61. define(`CPUVEC_offset',0)
  62. foreach(i,
  63. `FAT_ENTRY(MPN(i),CPUVEC_offset)
  64. define(`CPUVEC_offset',eval(CPUVEC_offset + 8))',
  65. CPUVEC_FUNCS_LIST)
  66. dnl  Usage: FAT_INIT(name, offset)
  67. dnl
  68. dnl  Emit a fat binary initializer function of the given name.  These
  69. dnl  functions are the initial values for the pointers in __gmpn_cpuvec.
  70. dnl
  71. dnl  The code simply calls __gmpn_cpuvec_init, and then jumps back through
  72. dnl  the __gmpn_cpuvec pointer, at the given "offset" (in bytes).
  73. dnl  __gmpn_cpuvec_init will have stored the address of the selected
  74. dnl  implementation there.
  75. dnl
  76. dnl  Only one of these routines will be executed, and only once, since after
  77. dnl  that all the __gmpn_cpuvec pointers go to real routines.  So there's no
  78. dnl  need for anything special here, just something small and simple.  To
  79. dnl  keep code size down, "fat_init" is a shared bit of code, arrived at
  80. dnl  with the offset in %al.  %al is used since the movb instruction is 2
  81. dnl  bytes where %eax would be 4.
  82. dnl
  83. dnl  Note having `PROLOGUE in FAT_INIT obscures that PROLOGUE from the
  84. dnl  HAVE_NATIVE grepping in configure, preventing that code trying to eval
  85. dnl  something with $1 in it.
  86. dnl
  87. dnl  We need to preserve parameter registers over the __gmpn_cpuvec_init call
  88. define(FAT_INIT,
  89. m4_assert_numargs(2)
  90. `PROLOGUE($1)
  91. mov $`'$2, %al
  92. jmp L(fat_init)
  93. EPILOGUE()
  94. ')
  95. L(fat_init):
  96. C al __gmpn_cpuvec byte offset
  97. movzbl %al, %eax
  98. push %rdi
  99. push %rsi
  100. push %rdx
  101. push %rcx
  102. push %r8
  103. push %r9
  104. push %rax
  105. CALL( __gmpn_cpuvec_init)
  106. pop %rax
  107. pop %r9
  108. pop %r8
  109. pop %rcx
  110. pop %rdx
  111. pop %rsi
  112. pop %rdi
  113. ifdef(`PIC',`
  114. LEA( GSYM_PREFIX`'__gmpn_cpuvec, %r10)
  115. jmp *(%r10,%rax)
  116. ',`dnl non-PIC
  117. jmp *GSYM_PREFIX`'__gmpn_cpuvec(%rax)
  118. ')
  119. dnl  FAT_INIT for each CPUVEC_FUNCS_LIST
  120. dnl
  121. define(`CPUVEC_offset',0)
  122. foreach(i,
  123. `FAT_INIT(MPN(i`'_init),CPUVEC_offset)
  124. define(`CPUVEC_offset',eval(CPUVEC_offset + 8))',
  125. CPUVEC_FUNCS_LIST)
  126. C long __gmpn_cpuid (char dst[12], int id);
  127. C
  128. C This is called only once, so just something simple and compact is fine.
  129. PROLOGUE(__gmpn_cpuid)
  130. mov %rbx, %r8
  131. mov %esi, %eax
  132. cpuid
  133. mov %ebx, (%rdi)
  134. mov %edx, 4(%rdi)
  135. mov %ecx, 8(%rdi)
  136. mov %r8, %rbx
  137. ret
  138. EPILOGUE()