github.com/aergoio/aergo@v1.3.1/libtool/src/gmp-6.1.2/mpn/x86/fat/fat.c (about) 1 /* x86 fat binary initializers. 2 3 THE FUNCTIONS AND VARIABLES IN THIS FILE ARE FOR INTERNAL USE ONLY. 4 THEY'RE ALMOST CERTAIN TO BE SUBJECT TO INCOMPATIBLE CHANGES OR DISAPPEAR 5 COMPLETELY IN FUTURE GNU MP RELEASES. 6 7 Copyright 2003, 2004, 2011-2013, 2015 Free Software Foundation, Inc. 8 9 This file is part of the GNU MP Library. 10 11 The GNU MP Library is free software; you can redistribute it and/or modify 12 it under the terms of either: 13 14 * the GNU Lesser General Public License as published by the Free 15 Software Foundation; either version 3 of the License, or (at your 16 option) any later version. 17 18 or 19 20 * the GNU General Public License as published by the Free Software 21 Foundation; either version 2 of the License, or (at your option) any 22 later version. 23 24 or both in parallel, as here. 25 26 The GNU MP Library is distributed in the hope that it will be useful, but 27 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 28 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 29 for more details. 30 31 You should have received copies of the GNU General Public License and the 32 GNU Lesser General Public License along with the GNU MP Library. If not, 33 see https://www.gnu.org/licenses/. */ 34 35 #include <stdio.h> /* for printf */ 36 #include <stdlib.h> /* for getenv */ 37 #include <string.h> 38 39 #include "gmp.h" 40 #include "gmp-impl.h" 41 42 /* Change this to "#define TRACE(x) x" for some traces. */ 43 #define TRACE(x) 44 45 46 /* fat_entry.asm */ 47 long __gmpn_cpuid (char [12], int); 48 int __gmpn_cpuid_available (void); 49 50 51 #if WANT_FAKE_CPUID 52 /* The "name"s in the table are values for the GMP_CPU_TYPE environment 53 variable. Anything can be used, but for now it's the canonical cpu types 54 as per config.guess/config.sub. */ 55 56 #define __gmpn_cpuid fake_cpuid 57 #define __gmpn_cpuid_available fake_cpuid_available 58 59 #define MAKE_FMS(family, model) \ 60 ((((family) & 0xf) << 8) + (((family) & 0xff0) << 20) \ 61 + (((model) & 0xf) << 4) + (((model) & 0xf0) << 12)) 62 63 static struct { 64 const char *name; 65 const char *vendor; 66 unsigned fms; 67 } fake_cpuid_table[] = { 68 { "i386", "" }, 69 { "i486", "GenuineIntel", MAKE_FMS (4, 0) }, 70 { "pentium", "GenuineIntel", MAKE_FMS (5, 0) }, 71 { "pentiummmx", "GenuineIntel", MAKE_FMS (5, 4) }, 72 { "pentiumpro", "GenuineIntel", MAKE_FMS (6, 0) }, 73 { "pentium2", "GenuineIntel", MAKE_FMS (6, 2) }, 74 { "pentium3", "GenuineIntel", MAKE_FMS (6, 7) }, 75 { "pentium4", "GenuineIntel", MAKE_FMS (15, 2) }, 76 { "prescott", "GenuineIntel", MAKE_FMS (15, 3) }, 77 { "nocona", "GenuineIntel", MAKE_FMS (15, 4) }, 78 { "core2", "GenuineIntel", MAKE_FMS (6, 0xf) }, 79 { "nehalem", "GenuineIntel", MAKE_FMS (6, 0x1a) }, 80 { "nhm", "GenuineIntel", MAKE_FMS (6, 0x1a) }, 81 { "atom", "GenuineIntel", MAKE_FMS (6, 0x1c) }, 82 { "westmere", "GenuineIntel", MAKE_FMS (6, 0x25) }, 83 { "wsm", "GenuineIntel", MAKE_FMS (6, 0x25) }, 84 { "sandybridge","GenuineIntel", MAKE_FMS (6, 0x2a) }, 85 { "sbr", "GenuineIntel", MAKE_FMS (6, 0x2a) }, 86 { "silvermont", "GenuineIntel", MAKE_FMS (6, 0x37) }, 87 { "slm", "GenuineIntel", MAKE_FMS (6, 0x37) }, 88 { "haswell", "GenuineIntel", MAKE_FMS (6, 0x3c) }, 89 { "hwl", "GenuineIntel", MAKE_FMS (6, 0x3c) }, 90 { "broadwell", "GenuineIntel", MAKE_FMS (6, 0x3d) }, 91 { "bwl", "GenuineIntel", MAKE_FMS (6, 0x3d) }, 92 { "skylake", "GenuineIntel", MAKE_FMS (6, 0x5e) }, 93 { "sky", "GenuineIntel", MAKE_FMS (6, 0x5e) }, 94 95 { "k5", "AuthenticAMD", MAKE_FMS (5, 0) }, 96 { "k6", "AuthenticAMD", MAKE_FMS (5, 3) }, 97 { "k62", "AuthenticAMD", MAKE_FMS (5, 8) }, 98 { "k63", "AuthenticAMD", MAKE_FMS (5, 9) }, 99 { "athlon", "AuthenticAMD", MAKE_FMS (6, 0) }, 100 { "k8", "AuthenticAMD", MAKE_FMS (15, 0) }, 101 { "k10", "AuthenticAMD", MAKE_FMS (16, 0) }, 102 { "bobcat", "AuthenticAMD", MAKE_FMS (20, 1) }, 103 { "bulldozer", "AuthenticAMD", MAKE_FMS (21, 1) }, 104 { "piledriver", "AuthenticAMD", MAKE_FMS (21, 2) }, 105 { "steamroller","AuthenticAMD", MAKE_FMS (21, 0x30) }, 106 { "excavator", "AuthenticAMD", MAKE_FMS (21, 0x60) }, 107 { "jaguar", "AuthenticAMD", MAKE_FMS (22, 1) }, 108 109 { "viac3", "CentaurHauls", MAKE_FMS (6, 0) }, 110 { "viac32", "CentaurHauls", MAKE_FMS (6, 9) }, 111 { "nano", "CentaurHauls", MAKE_FMS (6, 15) }, 112 }; 113 114 static int 115 fake_cpuid_lookup (void) 116 { 117 char *s; 118 int i; 119 120 s = getenv ("GMP_CPU_TYPE"); 121 if (s == NULL) 122 { 123 printf ("Need GMP_CPU_TYPE environment variable for fake cpuid\n"); 124 abort (); 125 } 126 127 for (i = 0; i < numberof (fake_cpuid_table); i++) 128 if (strcmp (s, fake_cpuid_table[i].name) == 0) 129 return i; 130 131 printf ("GMP_CPU_TYPE=%s unknown\n", s); 132 abort (); 133 } 134 135 static int 136 fake_cpuid_available (void) 137 { 138 return fake_cpuid_table[fake_cpuid_lookup()].vendor[0] != '\0'; 139 } 140 141 static long 142 fake_cpuid (char dst[12], int id) 143 { 144 int i = fake_cpuid_lookup(); 145 146 switch (id) { 147 case 0: 148 memcpy (dst, fake_cpuid_table[i].vendor, 12); 149 return 0; 150 case 1: 151 return fake_cpuid_table[i].fms; 152 default: 153 printf ("fake_cpuid(): oops, unknown id %d\n", id); 154 abort (); 155 } 156 } 157 #endif 158 159 160 typedef DECL_preinv_divrem_1 ((*preinv_divrem_1_t)); 161 typedef DECL_preinv_mod_1 ((*preinv_mod_1_t)); 162 163 struct cpuvec_t __gmpn_cpuvec = { 164 __MPN(add_n_init), 165 0, 166 0, 167 __MPN(addmul_1_init), 168 0, 169 __MPN(bdiv_dbm1c_init), 170 __MPN(cnd_add_n_init), 171 __MPN(cnd_sub_n_init), 172 __MPN(com_init), 173 __MPN(copyd_init), 174 __MPN(copyi_init), 175 __MPN(divexact_1_init), 176 __MPN(divrem_1_init), 177 __MPN(gcd_1_init), 178 __MPN(lshift_init), 179 __MPN(lshiftc_init), 180 __MPN(mod_1_init), 181 __MPN(mod_1_1p_init), 182 __MPN(mod_1_1p_cps_init), 183 __MPN(mod_1s_2p_init), 184 __MPN(mod_1s_2p_cps_init), 185 __MPN(mod_1s_4p_init), 186 __MPN(mod_1s_4p_cps_init), 187 __MPN(mod_34lsub1_init), 188 __MPN(modexact_1c_odd_init), 189 __MPN(mul_1_init), 190 __MPN(mul_basecase_init), 191 __MPN(mullo_basecase_init), 192 __MPN(preinv_divrem_1_init), 193 __MPN(preinv_mod_1_init), 194 __MPN(redc_1_init), 195 __MPN(redc_2_init), 196 __MPN(rshift_init), 197 __MPN(sqr_basecase_init), 198 __MPN(sub_n_init), 199 0, 200 __MPN(submul_1_init), 201 0 202 }; 203 204 int __gmpn_cpuvec_initialized = 0; 205 206 /* The following setups start with generic x86, then overwrite with 207 specifics for a chip, and higher versions of that chip. 208 209 The arrangement of the setups here will normally be the same as the $path 210 selections in configure.in for the respective chips. 211 212 This code is reentrant and thread safe. We always calculate the same 213 decided_cpuvec, so if two copies of the code are running it doesn't 214 matter which completes first, both write the same to __gmpn_cpuvec. 215 216 We need to go via decided_cpuvec because if one thread has completed 217 __gmpn_cpuvec then it may be making use of the threshold values in that 218 vector. If another thread is still running __gmpn_cpuvec_init then we 219 don't want it to write different values to those fields since some of the 220 asm routines only operate correctly up to their own defined threshold, 221 not an arbitrary value. */ 222 223 void 224 __gmpn_cpuvec_init (void) 225 { 226 struct cpuvec_t decided_cpuvec; 227 228 TRACE (printf ("__gmpn_cpuvec_init:\n")); 229 230 memset (&decided_cpuvec, '\0', sizeof (decided_cpuvec)); 231 232 CPUVEC_SETUP_x86; 233 CPUVEC_SETUP_fat; 234 235 if (! __gmpn_cpuid_available ()) 236 { 237 TRACE (printf (" 80386, or early 80486 without cpuid\n")); 238 } 239 else 240 { 241 char vendor_string[13]; 242 char dummy_string[12]; 243 long fms; 244 int family, model; 245 246 __gmpn_cpuid (vendor_string, 0); 247 vendor_string[12] = 0; 248 249 fms = __gmpn_cpuid (dummy_string, 1); 250 family = ((fms >> 8) & 0xf) + ((fms >> 20) & 0xff); 251 model = ((fms >> 4) & 0xf) + ((fms >> 12) & 0xf0); 252 253 if (strcmp (vendor_string, "GenuineIntel") == 0) 254 { 255 switch (family) 256 { 257 case 4: 258 TRACE (printf (" 80486 with cpuid\n")); 259 break; 260 261 case 5: 262 TRACE (printf (" pentium\n")); 263 CPUVEC_SETUP_pentium; 264 if (model >= 4) 265 { 266 TRACE (printf (" pentiummmx\n")); 267 CPUVEC_SETUP_pentium_mmx; 268 } 269 break; 270 271 case 6: 272 TRACE (printf (" p6\n")); 273 CPUVEC_SETUP_p6; 274 switch (model) 275 { 276 case 0x00: 277 case 0x01: 278 TRACE (printf (" pentiumpro\n")); 279 break; 280 281 case 0x02: 282 case 0x03: 283 case 0x04: 284 case 0x05: 285 case 0x06: 286 TRACE (printf (" pentium2\n")); 287 CPUVEC_SETUP_p6_mmx; 288 break; 289 290 case 0x07: 291 case 0x08: 292 case 0x0a: 293 case 0x0b: 294 case 0x0c: 295 TRACE (printf (" pentium3\n")); 296 CPUVEC_SETUP_p6_mmx; 297 CPUVEC_SETUP_p6_p3mmx; 298 break; 299 300 case 0x09: /* Banias */ 301 case 0x0d: /* Dothan */ 302 case 0x0e: /* Yonah */ 303 TRACE (printf (" Banias/Dothan/Yonah\n")); 304 CPUVEC_SETUP_p6_mmx; 305 CPUVEC_SETUP_p6_p3mmx; 306 CPUVEC_SETUP_p6_sse2; 307 break; 308 309 case 0x0f: /* Conroe Merom Kentsfield Allendale */ 310 case 0x10: 311 case 0x11: 312 case 0x12: 313 case 0x13: 314 case 0x14: 315 case 0x15: 316 case 0x16: 317 case 0x17: /* PNR Wolfdale Yorkfield */ 318 case 0x18: 319 case 0x19: 320 case 0x1d: /* PNR Dunnington */ 321 TRACE (printf (" Conroe\n")); 322 CPUVEC_SETUP_p6_mmx; 323 CPUVEC_SETUP_p6_p3mmx; 324 CPUVEC_SETUP_p6_sse2; 325 CPUVEC_SETUP_core2; 326 break; 327 328 case 0x1c: /* Atom Silverthorne */ 329 case 0x26: /* Atom Lincroft */ 330 case 0x27: /* Atom Saltwell */ 331 case 0x36: /* Atom Cedarview/Saltwell */ 332 TRACE (printf (" atom\n")); 333 CPUVEC_SETUP_atom; 334 CPUVEC_SETUP_atom_mmx; 335 CPUVEC_SETUP_atom_sse2; 336 break; 337 338 case 0x1a: /* NHM Gainestown */ 339 case 0x1b: 340 case 0x1e: /* NHM Lynnfield/Jasper */ 341 case 0x1f: 342 case 0x20: 343 case 0x21: 344 case 0x22: 345 case 0x23: 346 case 0x24: 347 case 0x25: /* WSM Clarkdale/Arrandale */ 348 case 0x28: 349 case 0x29: 350 case 0x2b: 351 case 0x2c: /* WSM Gulftown */ 352 case 0x2e: /* NHM Beckton */ 353 case 0x2f: /* WSM Eagleton */ 354 TRACE (printf (" nehalem/westmere\n")); 355 CPUVEC_SETUP_p6_mmx; 356 CPUVEC_SETUP_p6_p3mmx; 357 CPUVEC_SETUP_p6_sse2; 358 CPUVEC_SETUP_core2; 359 CPUVEC_SETUP_coreinhm; 360 break; 361 362 case 0x2a: /* SBR */ 363 case 0x2d: /* SBR-EP */ 364 case 0x3a: /* IBR */ 365 case 0x3c: /* Haswell */ 366 TRACE (printf (" sandybridge\n")); 367 CPUVEC_SETUP_p6_mmx; 368 CPUVEC_SETUP_p6_p3mmx; 369 CPUVEC_SETUP_p6_sse2; 370 CPUVEC_SETUP_core2; 371 CPUVEC_SETUP_coreinhm; 372 CPUVEC_SETUP_coreisbr; 373 break; 374 } 375 break; 376 377 case 15: 378 TRACE (printf (" pentium4\n")); 379 CPUVEC_SETUP_pentium4; 380 CPUVEC_SETUP_pentium4_mmx; 381 CPUVEC_SETUP_pentium4_sse2; 382 break; 383 } 384 } 385 else if (strcmp (vendor_string, "AuthenticAMD") == 0) 386 { 387 switch (family) 388 { 389 case 5: 390 if (model <= 3) 391 { 392 TRACE (printf (" k5\n")); 393 } 394 else 395 { 396 TRACE (printf (" k6\n")); 397 CPUVEC_SETUP_k6; 398 CPUVEC_SETUP_k6_mmx; 399 if (model >= 8) 400 { 401 TRACE (printf (" k62\n")); 402 CPUVEC_SETUP_k6_k62mmx; 403 } 404 if (model >= 9) 405 { 406 TRACE (printf (" k63\n")); 407 } 408 } 409 break; 410 case 6: 411 TRACE (printf (" athlon\n")); 412 CPUVEC_SETUP_k7; 413 CPUVEC_SETUP_k7_mmx; 414 break; 415 416 case 0x0f: /* k8 */ 417 case 0x11: /* "fam 11h", mix of k8 and k10 */ 418 case 0x13: /* unknown, conservatively assume k8 */ 419 case 0x16: /* unknown, conservatively assume k8 */ 420 case 0x17: /* unknown, conservatively assume k8 */ 421 TRACE (printf (" k8\n")); 422 CPUVEC_SETUP_k7; 423 CPUVEC_SETUP_k7_mmx; 424 CPUVEC_SETUP_k8; 425 break; 426 427 case 0x10: /* k10 */ 428 case 0x12: /* k10 (llano) */ 429 TRACE (printf (" k10\n")); 430 CPUVEC_SETUP_k7; 431 CPUVEC_SETUP_k7_mmx; 432 break; 433 434 case 0x14: /* bobcat */ 435 TRACE (printf (" bobcat\n")); 436 CPUVEC_SETUP_k7; 437 CPUVEC_SETUP_k7_mmx; 438 CPUVEC_SETUP_bobcat; 439 break; 440 441 case 0x15: /* bulldozer */ 442 TRACE (printf (" bulldozer\n")); 443 CPUVEC_SETUP_k7; 444 CPUVEC_SETUP_k7_mmx; 445 break; 446 } 447 } 448 else if (strcmp (vendor_string, "CentaurHauls") == 0) 449 { 450 switch (family) 451 { 452 case 6: 453 TRACE (printf (" viac3\n")); 454 if (model >= 9) 455 { 456 TRACE (printf (" viac32\n")); 457 } 458 if (model >= 15) 459 { 460 TRACE (printf (" nano\n")); 461 CPUVEC_SETUP_nano; 462 } 463 break; 464 } 465 } 466 else if (strcmp (vendor_string, "CyrixInstead") == 0) 467 { 468 /* Should recognize Cyrix' processors too. */ 469 TRACE (printf (" cyrix something\n")); 470 } 471 } 472 473 /* There's no x86 generic mpn_preinv_divrem_1 or mpn_preinv_mod_1. 474 Instead default to the plain versions from whichever CPU we detected. 475 The function arguments are compatible, no need for any glue code. */ 476 if (decided_cpuvec.preinv_divrem_1 == NULL) 477 decided_cpuvec.preinv_divrem_1 =(preinv_divrem_1_t)decided_cpuvec.divrem_1; 478 if (decided_cpuvec.preinv_mod_1 == NULL) 479 decided_cpuvec.preinv_mod_1 =(preinv_mod_1_t) decided_cpuvec.mod_1; 480 481 ASSERT_CPUVEC (decided_cpuvec); 482 CPUVEC_INSTALL (decided_cpuvec); 483 484 /* Set this once the threshold fields are ready. 485 Use volatile to prevent it getting moved. */ 486 *((volatile int *) &__gmpn_cpuvec_initialized) = 1; 487 }