1/* 2 * Copyright (C) 2010 The Android Open Source Project 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in 12 * the documentation and/or other materials provided with the 13 * distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 16 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 17 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 18 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 19 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29/* ChangeLog for this library: 30 * 31 * NDK r10e?: Add MIPS MSA feature. 32 * 33 * NDK r10: Support for 64-bit CPUs (Intel, ARM & MIPS). 34 * 35 * NDK r8d: Add android_setCpu(). 36 * 37 * NDK r8c: Add new ARM CPU features: VFPv2, VFP_D32, VFP_FP16, 38 * VFP_FMA, NEON_FMA, IDIV_ARM, IDIV_THUMB2 and iWMMXt. 39 * 40 * Rewrite the code to parse /proc/self/auxv instead of 41 * the "Features" field in /proc/cpuinfo. 42 * 43 * Dynamically allocate the buffer that hold the content 44 * of /proc/cpuinfo to deal with newer hardware. 45 * 46 * NDK r7c: Fix CPU count computation. The old method only reported the 47 * number of _active_ CPUs when the library was initialized, 48 * which could be less than the real total. 49 * 50 * NDK r5: Handle buggy kernels which report a CPU Architecture number of 7 51 * for an ARMv6 CPU (see below). 52 * 53 * Handle kernels that only report 'neon', and not 'vfpv3' 54 * (VFPv3 is mandated by the ARM architecture is Neon is implemented) 55 * 56 * Handle kernels that only report 'vfpv3d16', and not 'vfpv3' 57 * 58 * Fix x86 compilation. Report ANDROID_CPU_FAMILY_X86 in 59 * android_getCpuFamily(). 60 * 61 * NDK r4: Initial release 62 */ 63 64#include "cpu-features.h" 65 66#include <dlfcn.h> 67#include <errno.h> 68#include <fcntl.h> 69#include <pthread.h> 70#include <stdio.h> 71#include <stdlib.h> 72#include <string.h> 73#include <sys/system_properties.h> 74#include <unistd.h> 75 76static pthread_once_t g_once; 77static int g_inited; 78static AndroidCpuFamily g_cpuFamily; 79static uint64_t g_cpuFeatures; 80static int g_cpuCount; 81 82#ifdef __arm__ 83static uint32_t g_cpuIdArm; 84#endif 85 86static const int android_cpufeatures_debug = 0; 87 88#define D(...) \ 89 do { \ 90 if (android_cpufeatures_debug) { \ 91 printf(__VA_ARGS__); fflush(stdout); \ 92 } \ 93 } while (0) 94 95#ifdef __i386__ 96static __inline__ void x86_cpuid(int func, int values[4]) 97{ 98 int a, b, c, d; 99 /* We need to preserve ebx since we're compiling PIC code */ 100 /* this means we can't use "=b" for the second output register */ 101 __asm__ __volatile__ ( \ 102 "push %%ebx\n" 103 "cpuid\n" \ 104 "mov %%ebx, %1\n" 105 "pop %%ebx\n" 106 : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ 107 : "a" (func) \ 108 ); 109 values[0] = a; 110 values[1] = b; 111 values[2] = c; 112 values[3] = d; 113} 114#elif defined(__x86_64__) 115static __inline__ void x86_cpuid(int func, int values[4]) 116{ 117 int64_t a, b, c, d; 118 /* We need to preserve ebx since we're compiling PIC code */ 119 /* this means we can't use "=b" for the second output register */ 120 __asm__ __volatile__ ( \ 121 "push %%rbx\n" 122 "cpuid\n" \ 123 "mov %%rbx, %1\n" 124 "pop %%rbx\n" 125 : "=a" (a), "=r" (b), "=c" (c), "=d" (d) \ 126 : "a" (func) \ 127 ); 128 values[0] = a; 129 values[1] = b; 130 values[2] = c; 131 values[3] = d; 132} 133#endif 134 135/* Get the size of a file by reading it until the end. This is needed 136 * because files under /proc do not always return a valid size when 137 * using fseek(0, SEEK_END) + ftell(). Nor can they be mmap()-ed. 138 */ 139static int 140get_file_size(const char* pathname) 141{ 142 143 int fd, result = 0; 144 char buffer[256]; 145 146 fd = open(pathname, O_RDONLY); 147 if (fd < 0) { 148 D("Can't open %s: %s\n", pathname, strerror(errno)); 149 return -1; 150 } 151 152 for (;;) { 153 int ret = read(fd, buffer, sizeof buffer); 154 if (ret < 0) { 155 if (errno == EINTR) 156 continue; 157 D("Error while reading %s: %s\n", pathname, strerror(errno)); 158 break; 159 } 160 if (ret == 0) 161 break; 162 163 result += ret; 164 } 165 close(fd); 166 return result; 167} 168 169/* Read the content of /proc/cpuinfo into a user-provided buffer. 170 * Return the length of the data, or -1 on error. Does *not* 171 * zero-terminate the content. Will not read more 172 * than 'buffsize' bytes. 173 */ 174static int 175read_file(const char* pathname, char* buffer, size_t buffsize) 176{ 177 int fd, count; 178 179 fd = open(pathname, O_RDONLY); 180 if (fd < 0) { 181 D("Could not open %s: %s\n", pathname, strerror(errno)); 182 return -1; 183 } 184 count = 0; 185 while (count < (int)buffsize) { 186 int ret = read(fd, buffer + count, buffsize - count); 187 if (ret < 0) { 188 if (errno == EINTR) 189 continue; 190 D("Error while reading from %s: %s\n", pathname, strerror(errno)); 191 if (count == 0) 192 count = -1; 193 break; 194 } 195 if (ret == 0) 196 break; 197 count += ret; 198 } 199 close(fd); 200 return count; 201} 202 203#ifdef __arm__ 204/* Extract the content of a the first occurence of a given field in 205 * the content of /proc/cpuinfo and return it as a heap-allocated 206 * string that must be freed by the caller. 207 * 208 * Return NULL if not found 209 */ 210static char* 211extract_cpuinfo_field(const char* buffer, int buflen, const char* field) 212{ 213 int fieldlen = strlen(field); 214 const char* bufend = buffer + buflen; 215 char* result = NULL; 216 int len; 217 const char *p, *q; 218 219 /* Look for first field occurence, and ensures it starts the line. */ 220 p = buffer; 221 for (;;) { 222 p = memmem(p, bufend-p, field, fieldlen); 223 if (p == NULL) 224 goto EXIT; 225 226 if (p == buffer || p[-1] == '\n') 227 break; 228 229 p += fieldlen; 230 } 231 232 /* Skip to the first column followed by a space */ 233 p += fieldlen; 234 p = memchr(p, ':', bufend-p); 235 if (p == NULL || p[1] != ' ') 236 goto EXIT; 237 238 /* Find the end of the line */ 239 p += 2; 240 q = memchr(p, '\n', bufend-p); 241 if (q == NULL) 242 q = bufend; 243 244 /* Copy the line into a heap-allocated buffer */ 245 len = q-p; 246 result = malloc(len+1); 247 if (result == NULL) 248 goto EXIT; 249 250 memcpy(result, p, len); 251 result[len] = '\0'; 252 253EXIT: 254 return result; 255} 256 257/* Checks that a space-separated list of items contains one given 'item'. 258 * Returns 1 if found, 0 otherwise. 259 */ 260static int 261has_list_item(const char* list, const char* item) 262{ 263 const char* p = list; 264 int itemlen = strlen(item); 265 266 if (list == NULL) 267 return 0; 268 269 while (*p) { 270 const char* q; 271 272 /* skip spaces */ 273 while (*p == ' ' || *p == '\t') 274 p++; 275 276 /* find end of current list item */ 277 q = p; 278 while (*q && *q != ' ' && *q != '\t') 279 q++; 280 281 if (itemlen == q-p && !memcmp(p, item, itemlen)) 282 return 1; 283 284 /* skip to next item */ 285 p = q; 286 } 287 return 0; 288} 289#endif /* __arm__ */ 290 291/* Parse a number starting from 'input', but not going further 292 * than 'limit'. Return the value into '*result'. 293 * 294 * NOTE: Does not skip over leading spaces, or deal with sign characters. 295 * NOTE: Ignores overflows. 296 * 297 * The function returns NULL in case of error (bad format), or the new 298 * position after the decimal number in case of success (which will always 299 * be <= 'limit'). 300 */ 301static const char* 302parse_number(const char* input, const char* limit, int base, int* result) 303{ 304 const char* p = input; 305 int val = 0; 306 while (p < limit) { 307 int d = (*p - '0'); 308 if ((unsigned)d >= 10U) { 309 d = (*p - 'a'); 310 if ((unsigned)d >= 6U) 311 d = (*p - 'A'); 312 if ((unsigned)d >= 6U) 313 break; 314 d += 10; 315 } 316 if (d >= base) 317 break; 318 val = val*base + d; 319 p++; 320 } 321 if (p == input) 322 return NULL; 323 324 *result = val; 325 return p; 326} 327 328static const char* 329parse_decimal(const char* input, const char* limit, int* result) 330{ 331 return parse_number(input, limit, 10, result); 332} 333 334#ifdef __arm__ 335static const char* 336parse_hexadecimal(const char* input, const char* limit, int* result) 337{ 338 return parse_number(input, limit, 16, result); 339} 340#endif /* __arm__ */ 341 342/* This small data type is used to represent a CPU list / mask, as read 343 * from sysfs on Linux. See http://www.kernel.org/doc/Documentation/cputopology.txt 344 * 345 * For now, we don't expect more than 32 cores on mobile devices, so keep 346 * everything simple. 347 */ 348typedef struct { 349 uint32_t mask; 350} CpuList; 351 352static __inline__ void 353cpulist_init(CpuList* list) { 354 list->mask = 0; 355} 356 357static __inline__ void 358cpulist_and(CpuList* list1, CpuList* list2) { 359 list1->mask &= list2->mask; 360} 361 362static __inline__ void 363cpulist_set(CpuList* list, int index) { 364 if ((unsigned)index < 32) { 365 list->mask |= (uint32_t)(1U << index); 366 } 367} 368 369static __inline__ int 370cpulist_count(CpuList* list) { 371 return __builtin_popcount(list->mask); 372} 373 374/* Parse a textual list of cpus and store the result inside a CpuList object. 375 * Input format is the following: 376 * - comma-separated list of items (no spaces) 377 * - each item is either a single decimal number (cpu index), or a range made 378 * of two numbers separated by a single dash (-). Ranges are inclusive. 379 * 380 * Examples: 0 381 * 2,4-127,128-143 382 * 0-1 383 */ 384static void 385cpulist_parse(CpuList* list, const char* line, int line_len) 386{ 387 const char* p = line; 388 const char* end = p + line_len; 389 const char* q; 390 391 /* NOTE: the input line coming from sysfs typically contains a 392 * trailing newline, so take care of it in the code below 393 */ 394 while (p < end && *p != '\n') 395 { 396 int val, start_value, end_value; 397 398 /* Find the end of current item, and put it into 'q' */ 399 q = memchr(p, ',', end-p); 400 if (q == NULL) { 401 q = end; 402 } 403 404 /* Get first value */ 405 p = parse_decimal(p, q, &start_value); 406 if (p == NULL) 407 goto BAD_FORMAT; 408 409 end_value = start_value; 410 411 /* If we're not at the end of the item, expect a dash and 412 * and integer; extract end value. 413 */ 414 if (p < q && *p == '-') { 415 p = parse_decimal(p+1, q, &end_value); 416 if (p == NULL) 417 goto BAD_FORMAT; 418 } 419 420 /* Set bits CPU list bits */ 421 for (val = start_value; val <= end_value; val++) { 422 cpulist_set(list, val); 423 } 424 425 /* Jump to next item */ 426 p = q; 427 if (p < end) 428 p++; 429 } 430 431BAD_FORMAT: 432 ; 433} 434 435/* Read a CPU list from one sysfs file */ 436static void 437cpulist_read_from(CpuList* list, const char* filename) 438{ 439 char file[64]; 440 int filelen; 441 442 cpulist_init(list); 443 444 filelen = read_file(filename, file, sizeof file); 445 if (filelen < 0) { 446 D("Could not read %s: %s\n", filename, strerror(errno)); 447 return; 448 } 449 450 cpulist_parse(list, file, filelen); 451} 452#if defined(__aarch64__) 453// see <uapi/asm/hwcap.h> kernel header 454#define HWCAP_FP (1 << 0) 455#define HWCAP_ASIMD (1 << 1) 456#define HWCAP_AES (1 << 3) 457#define HWCAP_PMULL (1 << 4) 458#define HWCAP_SHA1 (1 << 5) 459#define HWCAP_SHA2 (1 << 6) 460#define HWCAP_CRC32 (1 << 7) 461#endif 462 463#if defined(__arm__) 464 465// See <asm/hwcap.h> kernel header. 466#define HWCAP_VFP (1 << 6) 467#define HWCAP_IWMMXT (1 << 9) 468#define HWCAP_NEON (1 << 12) 469#define HWCAP_VFPv3 (1 << 13) 470#define HWCAP_VFPv3D16 (1 << 14) 471#define HWCAP_VFPv4 (1 << 16) 472#define HWCAP_IDIVA (1 << 17) 473#define HWCAP_IDIVT (1 << 18) 474 475// see <uapi/asm/hwcap.h> kernel header 476#define HWCAP2_AES (1 << 0) 477#define HWCAP2_PMULL (1 << 1) 478#define HWCAP2_SHA1 (1 << 2) 479#define HWCAP2_SHA2 (1 << 3) 480#define HWCAP2_CRC32 (1 << 4) 481 482// This is the list of 32-bit ARMv7 optional features that are _always_ 483// supported by ARMv8 CPUs, as mandated by the ARM Architecture Reference 484// Manual. 485#define HWCAP_SET_FOR_ARMV8 \ 486 ( HWCAP_VFP | \ 487 HWCAP_NEON | \ 488 HWCAP_VFPv3 | \ 489 HWCAP_VFPv4 | \ 490 HWCAP_IDIVA | \ 491 HWCAP_IDIVT ) 492#endif 493 494#if defined(__mips__) 495// see <uapi/asm/hwcap.h> kernel header 496#define HWCAP_MIPS_R6 (1 << 0) 497#define HWCAP_MIPS_MSA (1 << 1) 498#endif 499 500#if defined(__arm__) || defined(__aarch64__) || defined(__mips__) 501 502#define AT_HWCAP 16 503#define AT_HWCAP2 26 504 505// Probe the system's C library for a 'getauxval' function and call it if 506// it exits, or return 0 for failure. This function is available since API 507// level 20. 508// 509// This code does *NOT* check for '__ANDROID_API__ >= 20' to support the 510// edge case where some NDK developers use headers for a platform that is 511// newer than the one really targetted by their application. 512// This is typically done to use newer native APIs only when running on more 513// recent Android versions, and requires careful symbol management. 514// 515// Note that getauxval() can't really be re-implemented here, because 516// its implementation does not parse /proc/self/auxv. Instead it depends 517// on values that are passed by the kernel at process-init time to the 518// C runtime initialization layer. 519static uint32_t 520get_elf_hwcap_from_getauxval(int hwcap_type) { 521 typedef unsigned long getauxval_func_t(unsigned long); 522 523 dlerror(); 524 void* libc_handle = dlopen("libc.so", RTLD_NOW); 525 if (!libc_handle) { 526 D("Could not dlopen() C library: %s\n", dlerror()); 527 return 0; 528 } 529 530 uint32_t ret = 0; 531 getauxval_func_t* func = (getauxval_func_t*) 532 dlsym(libc_handle, "getauxval"); 533 if (!func) { 534 D("Could not find getauxval() in C library\n"); 535 } else { 536 // Note: getauxval() returns 0 on failure. Doesn't touch errno. 537 ret = (uint32_t)(*func)(hwcap_type); 538 } 539 dlclose(libc_handle); 540 return ret; 541} 542#endif 543 544#if defined(__arm__) 545// Parse /proc/self/auxv to extract the ELF HW capabilities bitmap for the 546// current CPU. Note that this file is not accessible from regular 547// application processes on some Android platform releases. 548// On success, return new ELF hwcaps, or 0 on failure. 549static uint32_t 550get_elf_hwcap_from_proc_self_auxv(void) { 551 const char filepath[] = "/proc/self/auxv"; 552 int fd = TEMP_FAILURE_RETRY(open(filepath, O_RDONLY)); 553 if (fd < 0) { 554 D("Could not open %s: %s\n", filepath, strerror(errno)); 555 return 0; 556 } 557 558 struct { uint32_t tag; uint32_t value; } entry; 559 560 uint32_t result = 0; 561 for (;;) { 562 int ret = TEMP_FAILURE_RETRY(read(fd, (char*)&entry, sizeof entry)); 563 if (ret < 0) { 564 D("Error while reading %s: %s\n", filepath, strerror(errno)); 565 break; 566 } 567 // Detect end of list. 568 if (ret == 0 || (entry.tag == 0 && entry.value == 0)) 569 break; 570 if (entry.tag == AT_HWCAP) { 571 result = entry.value; 572 break; 573 } 574 } 575 close(fd); 576 return result; 577} 578 579/* Compute the ELF HWCAP flags from the content of /proc/cpuinfo. 580 * This works by parsing the 'Features' line, which lists which optional 581 * features the device's CPU supports, on top of its reference 582 * architecture. 583 */ 584static uint32_t 585get_elf_hwcap_from_proc_cpuinfo(const char* cpuinfo, int cpuinfo_len) { 586 uint32_t hwcaps = 0; 587 long architecture = 0; 588 char* cpuArch = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "CPU architecture"); 589 if (cpuArch) { 590 architecture = strtol(cpuArch, NULL, 10); 591 free(cpuArch); 592 593 if (architecture >= 8L) { 594 // This is a 32-bit ARM binary running on a 64-bit ARM64 kernel. 595 // The 'Features' line only lists the optional features that the 596 // device's CPU supports, compared to its reference architecture 597 // which are of no use for this process. 598 D("Faking 32-bit ARM HWCaps on ARMv%ld CPU\n", architecture); 599 return HWCAP_SET_FOR_ARMV8; 600 } 601 } 602 603 char* cpuFeatures = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "Features"); 604 if (cpuFeatures != NULL) { 605 D("Found cpuFeatures = '%s'\n", cpuFeatures); 606 607 if (has_list_item(cpuFeatures, "vfp")) 608 hwcaps |= HWCAP_VFP; 609 if (has_list_item(cpuFeatures, "vfpv3")) 610 hwcaps |= HWCAP_VFPv3; 611 if (has_list_item(cpuFeatures, "vfpv3d16")) 612 hwcaps |= HWCAP_VFPv3D16; 613 if (has_list_item(cpuFeatures, "vfpv4")) 614 hwcaps |= HWCAP_VFPv4; 615 if (has_list_item(cpuFeatures, "neon")) 616 hwcaps |= HWCAP_NEON; 617 if (has_list_item(cpuFeatures, "idiva")) 618 hwcaps |= HWCAP_IDIVA; 619 if (has_list_item(cpuFeatures, "idivt")) 620 hwcaps |= HWCAP_IDIVT; 621 if (has_list_item(cpuFeatures, "idiv")) 622 hwcaps |= HWCAP_IDIVA | HWCAP_IDIVT; 623 if (has_list_item(cpuFeatures, "iwmmxt")) 624 hwcaps |= HWCAP_IWMMXT; 625 626 free(cpuFeatures); 627 } 628 return hwcaps; 629} 630#endif /* __arm__ */ 631 632/* Return the number of cpus present on a given device. 633 * 634 * To handle all weird kernel configurations, we need to compute the 635 * intersection of the 'present' and 'possible' CPU lists and count 636 * the result. 637 */ 638static int 639get_cpu_count(void) 640{ 641 CpuList cpus_present[1]; 642 CpuList cpus_possible[1]; 643 644 cpulist_read_from(cpus_present, "/sys/devices/system/cpu/present"); 645 cpulist_read_from(cpus_possible, "/sys/devices/system/cpu/possible"); 646 647 /* Compute the intersection of both sets to get the actual number of 648 * CPU cores that can be used on this device by the kernel. 649 */ 650 cpulist_and(cpus_present, cpus_possible); 651 652 return cpulist_count(cpus_present); 653} 654 655static void 656android_cpuInitFamily(void) 657{ 658#if defined(__arm__) 659 g_cpuFamily = ANDROID_CPU_FAMILY_ARM; 660#elif defined(__i386__) 661 g_cpuFamily = ANDROID_CPU_FAMILY_X86; 662#elif defined(__mips64) 663/* Needs to be before __mips__ since the compiler defines both */ 664 g_cpuFamily = ANDROID_CPU_FAMILY_MIPS64; 665#elif defined(__mips__) 666 g_cpuFamily = ANDROID_CPU_FAMILY_MIPS; 667#elif defined(__aarch64__) 668 g_cpuFamily = ANDROID_CPU_FAMILY_ARM64; 669#elif defined(__x86_64__) 670 g_cpuFamily = ANDROID_CPU_FAMILY_X86_64; 671#else 672 g_cpuFamily = ANDROID_CPU_FAMILY_UNKNOWN; 673#endif 674} 675 676static void 677android_cpuInit(void) 678{ 679 char* cpuinfo = NULL; 680 int cpuinfo_len; 681 682 android_cpuInitFamily(); 683 684 g_cpuFeatures = 0; 685 g_cpuCount = 1; 686 g_inited = 1; 687 688 cpuinfo_len = get_file_size("/proc/cpuinfo"); 689 if (cpuinfo_len < 0) { 690 D("cpuinfo_len cannot be computed!"); 691 return; 692 } 693 cpuinfo = malloc(cpuinfo_len); 694 if (cpuinfo == NULL) { 695 D("cpuinfo buffer could not be allocated"); 696 return; 697 } 698 cpuinfo_len = read_file("/proc/cpuinfo", cpuinfo, cpuinfo_len); 699 D("cpuinfo_len is (%d):\n%.*s\n", cpuinfo_len, 700 cpuinfo_len >= 0 ? cpuinfo_len : 0, cpuinfo); 701 702 if (cpuinfo_len < 0) /* should not happen */ { 703 free(cpuinfo); 704 return; 705 } 706 707 /* Count the CPU cores, the value may be 0 for single-core CPUs */ 708 g_cpuCount = get_cpu_count(); 709 if (g_cpuCount == 0) { 710 g_cpuCount = 1; 711 } 712 713 D("found cpuCount = %d\n", g_cpuCount); 714 715#ifdef __arm__ 716 { 717 /* Extract architecture from the "CPU Architecture" field. 718 * The list is well-known, unlike the the output of 719 * the 'Processor' field which can vary greatly. 720 * 721 * See the definition of the 'proc_arch' array in 722 * $KERNEL/arch/arm/kernel/setup.c and the 'c_show' function in 723 * same file. 724 */ 725 char* cpuArch = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "CPU architecture"); 726 727 if (cpuArch != NULL) { 728 char* end; 729 long archNumber; 730 int hasARMv7 = 0; 731 732 D("found cpuArch = '%s'\n", cpuArch); 733 734 /* read the initial decimal number, ignore the rest */ 735 archNumber = strtol(cpuArch, &end, 10); 736 737 /* Note that ARMv8 is upwards compatible with ARMv7. */ 738 if (end > cpuArch && archNumber >= 7) { 739 hasARMv7 = 1; 740 } 741 742 /* Unfortunately, it seems that certain ARMv6-based CPUs 743 * report an incorrect architecture number of 7! 744 * 745 * See http://code.google.com/p/android/issues/detail?id=10812 746 * 747 * We try to correct this by looking at the 'elf_format' 748 * field reported by the 'Processor' field, which is of the 749 * form of "(v7l)" for an ARMv7-based CPU, and "(v6l)" for 750 * an ARMv6-one. 751 */ 752 if (hasARMv7) { 753 char* cpuProc = extract_cpuinfo_field(cpuinfo, cpuinfo_len, 754 "Processor"); 755 if (cpuProc != NULL) { 756 D("found cpuProc = '%s'\n", cpuProc); 757 if (has_list_item(cpuProc, "(v6l)")) { 758 D("CPU processor and architecture mismatch!!\n"); 759 hasARMv7 = 0; 760 } 761 free(cpuProc); 762 } 763 } 764 765 if (hasARMv7) { 766 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_ARMv7; 767 } 768 769 /* The LDREX / STREX instructions are available from ARMv6 */ 770 if (archNumber >= 6) { 771 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_LDREX_STREX; 772 } 773 774 free(cpuArch); 775 } 776 777 /* Extract the list of CPU features from ELF hwcaps */ 778 uint32_t hwcaps = 0; 779 hwcaps = get_elf_hwcap_from_getauxval(AT_HWCAP); 780 if (!hwcaps) { 781 D("Parsing /proc/self/auxv to extract ELF hwcaps!\n"); 782 hwcaps = get_elf_hwcap_from_proc_self_auxv(); 783 } 784 if (!hwcaps) { 785 // Parsing /proc/self/auxv will fail from regular application 786 // processes on some Android platform versions, when this happens 787 // parse proc/cpuinfo instead. 788 D("Parsing /proc/cpuinfo to extract ELF hwcaps!\n"); 789 hwcaps = get_elf_hwcap_from_proc_cpuinfo(cpuinfo, cpuinfo_len); 790 } 791 792 if (hwcaps != 0) { 793 int has_vfp = (hwcaps & HWCAP_VFP); 794 int has_vfpv3 = (hwcaps & HWCAP_VFPv3); 795 int has_vfpv3d16 = (hwcaps & HWCAP_VFPv3D16); 796 int has_vfpv4 = (hwcaps & HWCAP_VFPv4); 797 int has_neon = (hwcaps & HWCAP_NEON); 798 int has_idiva = (hwcaps & HWCAP_IDIVA); 799 int has_idivt = (hwcaps & HWCAP_IDIVT); 800 int has_iwmmxt = (hwcaps & HWCAP_IWMMXT); 801 802 // The kernel does a poor job at ensuring consistency when 803 // describing CPU features. So lots of guessing is needed. 804 805 // 'vfpv4' implies VFPv3|VFP_FMA|FP16 806 if (has_vfpv4) 807 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3 | 808 ANDROID_CPU_ARM_FEATURE_VFP_FP16 | 809 ANDROID_CPU_ARM_FEATURE_VFP_FMA; 810 811 // 'vfpv3' or 'vfpv3d16' imply VFPv3. Note that unlike GCC, 812 // a value of 'vfpv3' doesn't necessarily mean that the D32 813 // feature is present, so be conservative. All CPUs in the 814 // field that support D32 also support NEON, so this should 815 // not be a problem in practice. 816 if (has_vfpv3 || has_vfpv3d16) 817 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3; 818 819 // 'vfp' is super ambiguous. Depending on the kernel, it can 820 // either mean VFPv2 or VFPv3. Make it depend on ARMv7. 821 if (has_vfp) { 822 if (g_cpuFeatures & ANDROID_CPU_ARM_FEATURE_ARMv7) 823 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3; 824 else 825 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2; 826 } 827 828 // Neon implies VFPv3|D32, and if vfpv4 is detected, NEON_FMA 829 if (has_neon) { 830 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3 | 831 ANDROID_CPU_ARM_FEATURE_NEON | 832 ANDROID_CPU_ARM_FEATURE_VFP_D32; 833 if (has_vfpv4) 834 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON_FMA; 835 } 836 837 // VFPv3 implies VFPv2 and ARMv7 838 if (g_cpuFeatures & ANDROID_CPU_ARM_FEATURE_VFPv3) 839 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2 | 840 ANDROID_CPU_ARM_FEATURE_ARMv7; 841 842 if (has_idiva) 843 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_ARM; 844 if (has_idivt) 845 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2; 846 847 if (has_iwmmxt) 848 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_iWMMXt; 849 } 850 851 /* Extract the list of CPU features from ELF hwcaps2 */ 852 uint32_t hwcaps2 = 0; 853 hwcaps2 = get_elf_hwcap_from_getauxval(AT_HWCAP2); 854 if (hwcaps2 != 0) { 855 int has_aes = (hwcaps2 & HWCAP2_AES); 856 int has_pmull = (hwcaps2 & HWCAP2_PMULL); 857 int has_sha1 = (hwcaps2 & HWCAP2_SHA1); 858 int has_sha2 = (hwcaps2 & HWCAP2_SHA2); 859 int has_crc32 = (hwcaps2 & HWCAP2_CRC32); 860 861 if (has_aes) 862 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_AES; 863 if (has_pmull) 864 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_PMULL; 865 if (has_sha1) 866 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_SHA1; 867 if (has_sha2) 868 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_SHA2; 869 if (has_crc32) 870 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_CRC32; 871 } 872 /* Extract the cpuid value from various fields */ 873 // The CPUID value is broken up in several entries in /proc/cpuinfo. 874 // This table is used to rebuild it from the entries. 875 static const struct CpuIdEntry { 876 const char* field; 877 char format; 878 char bit_lshift; 879 char bit_length; 880 } cpu_id_entries[] = { 881 { "CPU implementer", 'x', 24, 8 }, 882 { "CPU variant", 'x', 20, 4 }, 883 { "CPU part", 'x', 4, 12 }, 884 { "CPU revision", 'd', 0, 4 }, 885 }; 886 size_t i; 887 D("Parsing /proc/cpuinfo to recover CPUID\n"); 888 for (i = 0; 889 i < sizeof(cpu_id_entries)/sizeof(cpu_id_entries[0]); 890 ++i) { 891 const struct CpuIdEntry* entry = &cpu_id_entries[i]; 892 char* value = extract_cpuinfo_field(cpuinfo, 893 cpuinfo_len, 894 entry->field); 895 if (value == NULL) 896 continue; 897 898 D("field=%s value='%s'\n", entry->field, value); 899 char* value_end = value + strlen(value); 900 int val = 0; 901 const char* start = value; 902 const char* p; 903 if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X')) { 904 start += 2; 905 p = parse_hexadecimal(start, value_end, &val); 906 } else if (entry->format == 'x') 907 p = parse_hexadecimal(value, value_end, &val); 908 else 909 p = parse_decimal(value, value_end, &val); 910 911 if (p > (const char*)start) { 912 val &= ((1 << entry->bit_length)-1); 913 val <<= entry->bit_lshift; 914 g_cpuIdArm |= (uint32_t) val; 915 } 916 917 free(value); 918 } 919 920 // Handle kernel configuration bugs that prevent the correct 921 // reporting of CPU features. 922 static const struct CpuFix { 923 uint32_t cpuid; 924 uint64_t or_flags; 925 } cpu_fixes[] = { 926 /* The Nexus 4 (Qualcomm Krait) kernel configuration 927 * forgets to report IDIV support. */ 928 { 0x510006f2, ANDROID_CPU_ARM_FEATURE_IDIV_ARM | 929 ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2 }, 930 { 0x510006f3, ANDROID_CPU_ARM_FEATURE_IDIV_ARM | 931 ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2 }, 932 }; 933 size_t n; 934 for (n = 0; n < sizeof(cpu_fixes)/sizeof(cpu_fixes[0]); ++n) { 935 const struct CpuFix* entry = &cpu_fixes[n]; 936 937 if (g_cpuIdArm == entry->cpuid) 938 g_cpuFeatures |= entry->or_flags; 939 } 940 941 // Special case: The emulator-specific Android 4.2 kernel fails 942 // to report support for the 32-bit ARM IDIV instruction. 943 // Technically, this is a feature of the virtual CPU implemented 944 // by the emulator. Note that it could also support Thumb IDIV 945 // in the future, and this will have to be slightly updated. 946 char* hardware = extract_cpuinfo_field(cpuinfo, 947 cpuinfo_len, 948 "Hardware"); 949 if (hardware) { 950 if (!strcmp(hardware, "Goldfish") && 951 g_cpuIdArm == 0x4100c080 && 952 (g_cpuFamily & ANDROID_CPU_ARM_FEATURE_ARMv7) != 0) { 953 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_ARM; 954 } 955 free(hardware); 956 } 957 } 958#endif /* __arm__ */ 959#ifdef __aarch64__ 960 { 961 /* Extract the list of CPU features from ELF hwcaps */ 962 uint32_t hwcaps = 0; 963 hwcaps = get_elf_hwcap_from_getauxval(AT_HWCAP); 964 if (hwcaps != 0) { 965 int has_fp = (hwcaps & HWCAP_FP); 966 int has_asimd = (hwcaps & HWCAP_ASIMD); 967 int has_aes = (hwcaps & HWCAP_AES); 968 int has_pmull = (hwcaps & HWCAP_PMULL); 969 int has_sha1 = (hwcaps & HWCAP_SHA1); 970 int has_sha2 = (hwcaps & HWCAP_SHA2); 971 int has_crc32 = (hwcaps & HWCAP_CRC32); 972 973 if(has_fp == 0) { 974 D("ERROR: Floating-point unit missing, but is required by Android on AArch64 CPUs\n"); 975 } 976 if(has_asimd == 0) { 977 D("ERROR: ASIMD unit missing, but is required by Android on AArch64 CPUs\n"); 978 } 979 980 if (has_fp) 981 g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_FP; 982 if (has_asimd) 983 g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_ASIMD; 984 if (has_aes) 985 g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_AES; 986 if (has_pmull) 987 g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_PMULL; 988 if (has_sha1) 989 g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_SHA1; 990 if (has_sha2) 991 g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_SHA2; 992 if (has_crc32) 993 g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_CRC32; 994 } 995 } 996#endif /* __aarch64__ */ 997 998#if defined(__i386__) || defined(__x86_64__) 999 int regs[4]; 1000 1001/* According to http://en.wikipedia.org/wiki/CPUID */ 1002#define VENDOR_INTEL_b 0x756e6547 1003#define VENDOR_INTEL_c 0x6c65746e 1004#define VENDOR_INTEL_d 0x49656e69 1005 1006 x86_cpuid(0, regs); 1007 int vendorIsIntel = (regs[1] == VENDOR_INTEL_b && 1008 regs[2] == VENDOR_INTEL_c && 1009 regs[3] == VENDOR_INTEL_d); 1010 1011 x86_cpuid(1, regs); 1012 if ((regs[2] & (1 << 9)) != 0) { 1013 g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSSE3; 1014 } 1015 if ((regs[2] & (1 << 23)) != 0) { 1016 g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_POPCNT; 1017 } 1018 if ((regs[2] & (1 << 19)) != 0) { 1019 g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSE4_1; 1020 } 1021 if ((regs[2] & (1 << 20)) != 0) { 1022 g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SSE4_2; 1023 } 1024 if (vendorIsIntel && (regs[2] & (1 << 22)) != 0) { 1025 g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_MOVBE; 1026 } 1027 if ((regs[2] & (1 << 25)) != 0) { 1028 g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AES_NI; 1029 } 1030 if ((regs[2] & (1 << 28)) != 0) { 1031 g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AVX; 1032 } 1033 if ((regs[2] & (1 << 30)) != 0) { 1034 g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_RDRAND; 1035 } 1036 1037 x86_cpuid(7, regs); 1038 if ((regs[1] & (1 << 5)) != 0) { 1039 g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_AVX2; 1040 } 1041 if ((regs[1] & (1 << 29)) != 0) { 1042 g_cpuFeatures |= ANDROID_CPU_X86_FEATURE_SHA_NI; 1043 } 1044 1045 1046#endif 1047#if defined( __mips__) 1048 { /* MIPS and MIPS64 */ 1049 /* Extract the list of CPU features from ELF hwcaps */ 1050 uint32_t hwcaps = 0; 1051 hwcaps = get_elf_hwcap_from_getauxval(AT_HWCAP); 1052 if (hwcaps != 0) { 1053 int has_r6 = (hwcaps & HWCAP_MIPS_R6); 1054 int has_msa = (hwcaps & HWCAP_MIPS_MSA); 1055 if (has_r6) 1056 g_cpuFeatures |= ANDROID_CPU_MIPS_FEATURE_R6; 1057 if (has_msa) 1058 g_cpuFeatures |= ANDROID_CPU_MIPS_FEATURE_MSA; 1059 } 1060 } 1061#endif /* __mips__ */ 1062 1063 free(cpuinfo); 1064} 1065 1066 1067AndroidCpuFamily 1068android_getCpuFamily(void) 1069{ 1070 pthread_once(&g_once, android_cpuInit); 1071 return g_cpuFamily; 1072} 1073 1074 1075uint64_t 1076android_getCpuFeatures(void) 1077{ 1078 pthread_once(&g_once, android_cpuInit); 1079 return g_cpuFeatures; 1080} 1081 1082 1083int 1084android_getCpuCount(void) 1085{ 1086 pthread_once(&g_once, android_cpuInit); 1087 return g_cpuCount; 1088} 1089 1090static void 1091android_cpuInitDummy(void) 1092{ 1093 g_inited = 1; 1094} 1095 1096int 1097android_setCpu(int cpu_count, uint64_t cpu_features) 1098{ 1099 /* Fail if the library was already initialized. */ 1100 if (g_inited) 1101 return 0; 1102 1103 android_cpuInitFamily(); 1104 g_cpuCount = (cpu_count <= 0 ? 1 : cpu_count); 1105 g_cpuFeatures = cpu_features; 1106 pthread_once(&g_once, android_cpuInitDummy); 1107 1108 return 1; 1109} 1110 1111#ifdef __arm__ 1112uint32_t 1113android_getCpuIdArm(void) 1114{ 1115 pthread_once(&g_once, android_cpuInit); 1116 return g_cpuIdArm; 1117} 1118 1119int 1120android_setCpuArm(int cpu_count, uint64_t cpu_features, uint32_t cpu_id) 1121{ 1122 if (!android_setCpu(cpu_count, cpu_features)) 1123 return 0; 1124 1125 g_cpuIdArm = cpu_id; 1126 return 1; 1127} 1128#endif /* __arm__ */ 1129 1130/* 1131 * Technical note: Making sense of ARM's FPU architecture versions. 1132 * 1133 * FPA was ARM's first attempt at an FPU architecture. There is no Android 1134 * device that actually uses it since this technology was already obsolete 1135 * when the project started. If you see references to FPA instructions 1136 * somewhere, you can be sure that this doesn't apply to Android at all. 1137 * 1138 * FPA was followed by "VFP", soon renamed "VFPv1" due to the emergence of 1139 * new versions / additions to it. ARM considers this obsolete right now, 1140 * and no known Android device implements it either. 1141 * 1142 * VFPv2 added a few instructions to VFPv1, and is an *optional* extension 1143 * supported by some ARMv5TE, ARMv6 and ARMv6T2 CPUs. Note that a device 1144 * supporting the 'armeabi' ABI doesn't necessarily support these. 1145 * 1146 * VFPv3-D16 adds a few instructions on top of VFPv2 and is typically used 1147 * on ARMv7-A CPUs which implement a FPU. Note that it is also mandated 1148 * by the Android 'armeabi-v7a' ABI. The -D16 suffix in its name means 1149 * that it provides 16 double-precision FPU registers (d0-d15) and 32 1150 * single-precision ones (s0-s31) which happen to be mapped to the same 1151 * register banks. 1152 * 1153 * VFPv3-D32 is the name of an extension to VFPv3-D16 that provides 16 1154 * additional double precision registers (d16-d31). Note that there are 1155 * still only 32 single precision registers. 1156 * 1157 * VFPv3xD is a *subset* of VFPv3-D16 that only provides single-precision 1158 * registers. It is only used on ARMv7-M (i.e. on micro-controllers) which 1159 * are not supported by Android. Note that it is not compatible with VFPv2. 1160 * 1161 * NOTE: The term 'VFPv3' usually designate either VFPv3-D16 or VFPv3-D32 1162 * depending on context. For example GCC uses it for VFPv3-D32, but 1163 * the Linux kernel code uses it for VFPv3-D16 (especially in 1164 * /proc/cpuinfo). Always try to use the full designation when 1165 * possible. 1166 * 1167 * NEON, a.k.a. "ARM Advanced SIMD" is an extension that provides 1168 * instructions to perform parallel computations on vectors of 8, 16, 1169 * 32, 64 and 128 bit quantities. NEON requires VFPv32-D32 since all 1170 * NEON registers are also mapped to the same register banks. 1171 * 1172 * VFPv4-D16, adds a few instructions on top of VFPv3-D16 in order to 1173 * perform fused multiply-accumulate on VFP registers, as well as 1174 * half-precision (16-bit) conversion operations. 1175 * 1176 * VFPv4-D32 is VFPv4-D16 with 32, instead of 16, FPU double precision 1177 * registers. 1178 * 1179 * VPFv4-NEON is VFPv4-D32 with NEON instructions. It also adds fused 1180 * multiply-accumulate instructions that work on the NEON registers. 1181 * 1182 * NOTE: Similarly, "VFPv4" might either reference VFPv4-D16 or VFPv4-D32 1183 * depending on context. 1184 * 1185 * The following information was determined by scanning the binutils-2.22 1186 * sources: 1187 * 1188 * Basic VFP instruction subsets: 1189 * 1190 * #define FPU_VFP_EXT_V1xD 0x08000000 // Base VFP instruction set. 1191 * #define FPU_VFP_EXT_V1 0x04000000 // Double-precision insns. 1192 * #define FPU_VFP_EXT_V2 0x02000000 // ARM10E VFPr1. 1193 * #define FPU_VFP_EXT_V3xD 0x01000000 // VFPv3 single-precision. 1194 * #define FPU_VFP_EXT_V3 0x00800000 // VFPv3 double-precision. 1195 * #define FPU_NEON_EXT_V1 0x00400000 // Neon (SIMD) insns. 1196 * #define FPU_VFP_EXT_D32 0x00200000 // Registers D16-D31. 1197 * #define FPU_VFP_EXT_FP16 0x00100000 // Half-precision extensions. 1198 * #define FPU_NEON_EXT_FMA 0x00080000 // Neon fused multiply-add 1199 * #define FPU_VFP_EXT_FMA 0x00040000 // VFP fused multiply-add 1200 * 1201 * FPU types (excluding NEON) 1202 * 1203 * FPU_VFP_V1xD (EXT_V1xD) 1204 * | 1205 * +--------------------------+ 1206 * | | 1207 * FPU_VFP_V1 (+EXT_V1) FPU_VFP_V3xD (+EXT_V2+EXT_V3xD) 1208 * | | 1209 * | | 1210 * FPU_VFP_V2 (+EXT_V2) FPU_VFP_V4_SP_D16 (+EXT_FP16+EXT_FMA) 1211 * | 1212 * FPU_VFP_V3D16 (+EXT_Vx3D+EXT_V3) 1213 * | 1214 * +--------------------------+ 1215 * | | 1216 * FPU_VFP_V3 (+EXT_D32) FPU_VFP_V4D16 (+EXT_FP16+EXT_FMA) 1217 * | | 1218 * | FPU_VFP_V4 (+EXT_D32) 1219 * | 1220 * FPU_VFP_HARD (+EXT_FMA+NEON_EXT_FMA) 1221 * 1222 * VFP architectures: 1223 * 1224 * ARCH_VFP_V1xD (EXT_V1xD) 1225 * | 1226 * +------------------+ 1227 * | | 1228 * | ARCH_VFP_V3xD (+EXT_V2+EXT_V3xD) 1229 * | | 1230 * | ARCH_VFP_V3xD_FP16 (+EXT_FP16) 1231 * | | 1232 * | ARCH_VFP_V4_SP_D16 (+EXT_FMA) 1233 * | 1234 * ARCH_VFP_V1 (+EXT_V1) 1235 * | 1236 * ARCH_VFP_V2 (+EXT_V2) 1237 * | 1238 * ARCH_VFP_V3D16 (+EXT_V3xD+EXT_V3) 1239 * | 1240 * +-------------------+ 1241 * | | 1242 * | ARCH_VFP_V3D16_FP16 (+EXT_FP16) 1243 * | 1244 * +-------------------+ 1245 * | | 1246 * | ARCH_VFP_V4_D16 (+EXT_FP16+EXT_FMA) 1247 * | | 1248 * | ARCH_VFP_V4 (+EXT_D32) 1249 * | | 1250 * | ARCH_NEON_VFP_V4 (+EXT_NEON+EXT_NEON_FMA) 1251 * | 1252 * ARCH_VFP_V3 (+EXT_D32) 1253 * | 1254 * +-------------------+ 1255 * | | 1256 * | ARCH_VFP_V3_FP16 (+EXT_FP16) 1257 * | 1258 * ARCH_VFP_V3_PLUS_NEON_V1 (+EXT_NEON) 1259 * | 1260 * ARCH_NEON_FP16 (+EXT_FP16) 1261 * 1262 * -fpu=<name> values and their correspondance with FPU architectures above: 1263 * 1264 * {"vfp", FPU_ARCH_VFP_V2}, 1265 * {"vfp9", FPU_ARCH_VFP_V2}, 1266 * {"vfp3", FPU_ARCH_VFP_V3}, // For backwards compatbility. 1267 * {"vfp10", FPU_ARCH_VFP_V2}, 1268 * {"vfp10-r0", FPU_ARCH_VFP_V1}, 1269 * {"vfpxd", FPU_ARCH_VFP_V1xD}, 1270 * {"vfpv2", FPU_ARCH_VFP_V2}, 1271 * {"vfpv3", FPU_ARCH_VFP_V3}, 1272 * {"vfpv3-fp16", FPU_ARCH_VFP_V3_FP16}, 1273 * {"vfpv3-d16", FPU_ARCH_VFP_V3D16}, 1274 * {"vfpv3-d16-fp16", FPU_ARCH_VFP_V3D16_FP16}, 1275 * {"vfpv3xd", FPU_ARCH_VFP_V3xD}, 1276 * {"vfpv3xd-fp16", FPU_ARCH_VFP_V3xD_FP16}, 1277 * {"neon", FPU_ARCH_VFP_V3_PLUS_NEON_V1}, 1278 * {"neon-fp16", FPU_ARCH_NEON_FP16}, 1279 * {"vfpv4", FPU_ARCH_VFP_V4}, 1280 * {"vfpv4-d16", FPU_ARCH_VFP_V4D16}, 1281 * {"fpv4-sp-d16", FPU_ARCH_VFP_V4_SP_D16}, 1282 * {"neon-vfpv4", FPU_ARCH_NEON_VFP_V4}, 1283 * 1284 * 1285 * Simplified diagram that only includes FPUs supported by Android: 1286 * Only ARCH_VFP_V3D16 is actually mandated by the armeabi-v7a ABI, 1287 * all others are optional and must be probed at runtime. 1288 * 1289 * ARCH_VFP_V3D16 (EXT_V1xD+EXT_V1+EXT_V2+EXT_V3xD+EXT_V3) 1290 * | 1291 * +-------------------+ 1292 * | | 1293 * | ARCH_VFP_V3D16_FP16 (+EXT_FP16) 1294 * | 1295 * +-------------------+ 1296 * | | 1297 * | ARCH_VFP_V4_D16 (+EXT_FP16+EXT_FMA) 1298 * | | 1299 * | ARCH_VFP_V4 (+EXT_D32) 1300 * | | 1301 * | ARCH_NEON_VFP_V4 (+EXT_NEON+EXT_NEON_FMA) 1302 * | 1303 * ARCH_VFP_V3 (+EXT_D32) 1304 * | 1305 * +-------------------+ 1306 * | | 1307 * | ARCH_VFP_V3_FP16 (+EXT_FP16) 1308 * | 1309 * ARCH_VFP_V3_PLUS_NEON_V1 (+EXT_NEON) 1310 * | 1311 * ARCH_NEON_FP16 (+EXT_FP16) 1312 * 1313 */ 1314