github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/mpn/x86/fat/fat_entry.asm (about)

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