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