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

数学计算

开发平台:

Unix_Linux

  1. dnl  x86 fat binary entrypoints.
  2. dnl  Copyright 2003 Free Software Foundation, Inc.
  3. dnl
  4. dnl  This file is part of the GNU MP Library.
  5. dnl
  6. dnl  The GNU MP Library is free software; you can redistribute it and/or
  7. dnl  modify it under the terms of the GNU Lesser General Public License as
  8. dnl  published by the Free Software Foundation; either version 3 of the
  9. dnl  License, or (at your option) any later version.
  10. dnl
  11. dnl  The GNU MP Library is distributed in the hope that it will be useful,
  12. dnl  but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. dnl  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14. dnl  Lesser General Public License for more details.
  15. dnl
  16. dnl  You should have received a copy of the GNU Lesser General Public License
  17. dnl  along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.
  18. include(`../config.m4')
  19. dnl  Forcibly disable profiling.
  20. dnl
  21. dnl  The entrypoints and inits are small enough not to worry about, the real
  22. dnl  routines arrived at will have any profiling.  Also, the way the code
  23. dnl  here ends with a jump means we won't work properly with the
  24. dnl  "instrument" profiling scheme anyway.
  25. define(`WANT_PROFILING',no)
  26. TEXT
  27. dnl  Usage: FAT_ENTRY(name, offset)
  28. dnl
  29. dnl  Emit a fat binary entrypoint function of the given name.  This is the
  30. dnl  normal entry for applications, eg. __gmpn_add_n.
  31. dnl
  32. dnl  The code simply jumps through the function pointer in __gmpn_cpuvec at
  33. dnl  the given "offset" (in bytes).
  34. dnl
  35. dnl  For non-PIC, the jumps are 5 bytes each, aligning them to 8 should be
  36. dnl  fine for all x86s.
  37. dnl
  38. dnl  For PIC, the jumps are 20 bytes each, and are best aligned to 16 to
  39. dnl  ensure at least the first two instructions don't cross a cache line
  40. dnl  boundary.
  41. dnl
  42. dnl  Note the extra `' ahead of PROLOGUE obscures it from the HAVE_NATIVE
  43. dnl  grepping in configure, stopping that code trying to eval something with
  44. dnl  $1 in it.
  45. define(FAT_ENTRY,
  46. m4_assert_numargs(2)
  47. ` ALIGN(ifdef(`PIC',16,8))
  48. `'PROLOGUE($1)
  49. ifdef(`PIC',
  50. ` call L(movl_eip_edx)
  51. L(entry_here$2):
  52. addl $_GLOBAL_OFFSET_TABLE_+[.-L(entry_here$2)], %edx
  53. movl GSYM_PREFIX`'__gmpn_cpuvec@GOT(%edx), %edx
  54. jmp *m4_empty_if_zero($2)(%edx)
  55. ',`dnl non-PIC
  56. jmp *GSYM_PREFIX`'__gmpn_cpuvec+$2
  57. ')
  58. EPILOGUE()
  59. ')
  60. dnl  FAT_ENTRY for each CPUVEC_FUNCS_LIST
  61. dnl
  62. define(`CPUVEC_offset',0)
  63. foreach(i,
  64. `FAT_ENTRY(MPN(i),CPUVEC_offset)
  65. define(`CPUVEC_offset',eval(CPUVEC_offset + 4))',
  66. CPUVEC_FUNCS_LIST)
  67. ifdef(`PIC',`
  68. ALIGN(8)
  69. L(movl_eip_edx):
  70. movl (%esp), %edx
  71. ret_internal
  72. ')
  73. dnl  Usage: FAT_INIT(name, offset)
  74. dnl
  75. dnl  Emit a fat binary initializer function of the given name.  These
  76. dnl  functions are the initial values for the pointers in __gmpn_cpuvec.
  77. dnl
  78. dnl  The code simply calls __gmpn_cpuvec_init, and then jumps back through
  79. dnl  the __gmpn_cpuvec pointer, at the given "offset" (in bytes).
  80. dnl  __gmpn_cpuvec_init will have stored the address of the selected
  81. dnl  implementation there.
  82. dnl
  83. dnl  Only one of these routines will be executed, and only once, since after
  84. dnl  that all the __gmpn_cpuvec pointers go to real routines.  So there's no
  85. dnl  need for anything special here, just something small and simple.  To
  86. dnl  keep code size down, "fat_init" is a shared bit of code, arrived at
  87. dnl  with the offset in %al.  %al is used since the movb instruction is 2
  88. dnl  bytes where %eax would be 4.
  89. dnl
  90. dnl  Note having `PROLOGUE in FAT_INIT obscures that PROLOGUE from the
  91. dnl  HAVE_NATIVE grepping in configure, preventing that code trying to eval
  92. dnl  something with $1 in it.
  93. define(FAT_INIT,
  94. m4_assert_numargs(2)
  95. `PROLOGUE($1)
  96. movb $`'$2, %al
  97. jmp L(fat_init)
  98. EPILOGUE()
  99. ')
  100. L(fat_init):
  101. C al __gmpn_cpuvec byte offset
  102. movsbl %al, %eax
  103. pushl %eax
  104. ifdef(`PIC',`
  105. pushl %ebx
  106. call L(movl_eip_ebx)
  107. L(init_here):
  108. addl $_GLOBAL_OFFSET_TABLE_+[.-L(init_here)], %ebx
  109. call GSYM_PREFIX`'__gmpn_cpuvec_init@PLT
  110. movl GSYM_PREFIX`'__gmpn_cpuvec@GOT(%ebx), %edx
  111. popl %ebx
  112. popl %eax
  113. jmp *(%edx,%eax)
  114. L(movl_eip_ebx):
  115. movl (%esp), %ebx
  116. ret_internal
  117. ',`dnl non-PIC
  118. call GSYM_PREFIX`'__gmpn_cpuvec_init
  119. popl %eax
  120. jmp *GSYM_PREFIX`'__gmpn_cpuvec(%eax)
  121. ')
  122. dnl  FAT_INIT for each CPUVEC_FUNCS_LIST
  123. dnl
  124. define(`CPUVEC_offset',0)
  125. foreach(i,
  126. `FAT_INIT(MPN(i`'_init),CPUVEC_offset)
  127. define(`CPUVEC_offset',eval(CPUVEC_offset + 4))',
  128. CPUVEC_FUNCS_LIST)
  129. C long __gmpn_cpuid (char dst[12], int id);
  130. C
  131. C This is called only once, so just something simple and compact is fine.
  132. defframe(PARAM_ID,  8)
  133. defframe(PARAM_DST, 4)
  134. deflit(`FRAME',0)
  135. PROLOGUE(__gmpn_cpuid)
  136. pushl %esi FRAME_pushl()
  137. pushl %ebx FRAME_pushl()
  138. movl PARAM_ID, %eax
  139. cpuid
  140. movl PARAM_DST, %esi
  141. movl %ebx, (%esi)
  142. movl %edx, 4(%esi)
  143. movl %ecx, 8(%esi)
  144. popl %ebx
  145. popl %esi
  146. ret
  147. EPILOGUE()
  148. C int __gmpn_cpuid_available (void);
  149. C
  150. C Return non-zero if the cpuid instruction is available, which means late
  151. C model 80486 and higher.  80386 and early 80486 don't have cpuid.
  152. C
  153. C The test follows Intel AP-485 application note, namely that if bit 21 is
  154. C modifiable then cpuid is supported.  This test is reentrant and thread
  155. C safe, since of course any interrupt or context switch will preserve the
  156. C flags while we're tinkering with them.
  157. C
  158. C This is called only once, so just something simple and compact is fine.
  159. PROLOGUE(__gmpn_cpuid_available)
  160. pushf
  161. popl %ecx C old flags
  162. movl %ecx, %edx
  163. xorl $0x200000, %edx
  164. pushl %edx
  165. popf
  166. pushf
  167. popl %edx C tweaked flags
  168. movl $1, %eax
  169. cmpl %ecx, %edx
  170. jne L(available)
  171. xorl %eax, %eax C not changed, so cpuid not available
  172. L(available):
  173. ret
  174. EPILOGUE()