1 dnl x86 fat binary entrypoints.
3 dnl Copyright 2003 Free Software Foundation, Inc.
5 dnl This file is part of the GNU MP Library.
7 dnl The GNU MP Library is free software; you can redistribute it and/or
8 dnl modify it under the terms of the GNU Lesser General Public License as
9 dnl published by the Free Software Foundation; either version 3 of the
10 dnl License, or (at your option) any later version.
12 dnl The GNU MP Library is distributed in the hope that it will be useful,
13 dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
14 dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 dnl Lesser General Public License for more details.
17 dnl You should have received a copy of the GNU Lesser General Public License
18 dnl along with the GNU MP Library. If not, see http://www.gnu.org/licenses/.
20 include(`../config.m4')
23 dnl Forcibly disable profiling.
25 dnl The entrypoints and inits are small enough not to worry about, the real
26 dnl routines arrived at will have any profiling. Also, the way the code
27 dnl here ends with a jump means we won't work properly with the
28 dnl "instrument" profiling scheme anyway.
30 define(`WANT_PROFILING',no)
36 dnl Usage: FAT_ENTRY(name, offset)
38 dnl Emit a fat binary entrypoint function of the given name. This is the
39 dnl normal entry for applications, eg. __gmpn_add_n.
41 dnl The code simply jumps through the function pointer in __gmpn_cpuvec at
42 dnl the given "offset" (in bytes).
44 dnl For non-PIC, the jumps are 5 bytes each, aligning them to 8 should be
45 dnl fine for all x86s.
47 dnl For PIC, the jumps are 20 bytes each, and are best aligned to 16 to
48 dnl ensure at least the first two instructions don't cross a cache line
51 dnl Note the extra `' ahead of PROLOGUE obscures it from the HAVE_NATIVE
52 dnl grepping in configure, stopping that code trying to eval something with
57 ` ALIGN(ifdef(`PIC',16,8))
60 ` call L(movl_eip_edx)
62 addl $_GLOBAL_OFFSET_TABLE_+[.-L(entry_here$2)], %edx
63 movl GSYM_PREFIX`'__gmpn_cpuvec@GOT(%edx), %edx
64 jmp *m4_empty_if_zero($2)(%edx)
66 jmp *GSYM_PREFIX`'__gmpn_cpuvec+$2
72 dnl FAT_ENTRY for each CPUVEC_FUNCS_LIST
75 define(`CPUVEC_offset',0)
77 `FAT_ENTRY(MPN(i),CPUVEC_offset)
78 define(`CPUVEC_offset',eval(CPUVEC_offset + 4))',
89 dnl Usage: FAT_INIT(name, offset)
91 dnl Emit a fat binary initializer function of the given name. These
92 dnl functions are the initial values for the pointers in __gmpn_cpuvec.
94 dnl The code simply calls __gmpn_cpuvec_init, and then jumps back through
95 dnl the __gmpn_cpuvec pointer, at the given "offset" (in bytes).
96 dnl __gmpn_cpuvec_init will have stored the address of the selected
97 dnl implementation there.
99 dnl Only one of these routines will be executed, and only once, since after
100 dnl that all the __gmpn_cpuvec pointers go to real routines. So there's no
101 dnl need for anything special here, just something small and simple. To
102 dnl keep code size down, "fat_init" is a shared bit of code, arrived at
103 dnl with the offset in %al. %al is used since the movb instruction is 2
104 dnl bytes where %eax would be 4.
106 dnl Note having `PROLOGUE in FAT_INIT obscures that PROLOGUE from the
107 dnl HAVE_NATIVE grepping in configure, preventing that code trying to eval
108 dnl something with $1 in it.
119 C al __gmpn_cpuvec byte offset
128 addl $_GLOBAL_OFFSET_TABLE_+[.-L(init_here)], %ebx
129 call GSYM_PREFIX`'__gmpn_cpuvec_init@PLT
130 movl GSYM_PREFIX`'__gmpn_cpuvec@GOT(%ebx), %edx
140 call GSYM_PREFIX`'__gmpn_cpuvec_init
142 jmp *GSYM_PREFIX`'__gmpn_cpuvec(%eax)
145 dnl FAT_INIT for each CPUVEC_FUNCS_LIST
148 define(`CPUVEC_offset',0)
150 `FAT_INIT(MPN(i`'_init),CPUVEC_offset)
151 define(`CPUVEC_offset',eval(CPUVEC_offset + 4))',
156 C long __gmpn_cpuid (char dst[12], int id);
158 C This is called only once, so just something simple and compact is fine.
160 defframe(PARAM_ID, 8)
161 defframe(PARAM_DST, 4)
164 PROLOGUE(__gmpn_cpuid)
165 pushl %esi FRAME_pushl()
166 pushl %ebx FRAME_pushl()
179 C int __gmpn_cpuid_available (void);
181 C Return non-zero if the cpuid instruction is available, which means late
182 C model 80486 and higher. 80386 and early 80486 don't have cpuid.
184 C The test follows Intel AP-485 application note, namely that if bit 21 is
185 C modifiable then cpuid is supported. This test is reentrant and thread
186 C safe, since of course any interrupt or context switch will preserve the
187 C flags while we're tinkering with them.
189 C This is called only once, so just something simple and compact is fine.
191 PROLOGUE(__gmpn_cpuid_available)
193 popl %ecx C old flags
200 popl %edx C tweaked flags
205 xorl %eax, %eax C not changed, so cpuid not available