Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(246)

Side by Side Diff: platform_tools/android/third_party/cpufeatures/cpu-features.c

Issue 858233003: Update the version of cpu-features that we use for testing. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « platform_tools/android/third_party/cpufeatures/cpu-features.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2010 The Android Open Source Project 2 * Copyright (C) 2010 The Android Open Source Project
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions 6 * modification, are permitted provided that the following conditions
7 * are met: 7 * are met:
8 * * Redistributions of source code must retain the above copyright 8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer. 9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright 10 * * Redistributions in binary form must reproduce the above copyright
(...skipping 10 matching lines...) Expand all
21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 21 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 22 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 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 25 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE. 26 * SUCH DAMAGE.
27 */ 27 */
28 28
29 /* ChangeLog for this library: 29 /* ChangeLog for this library:
30 * 30 *
31 * NDK r9?: Support for 64-bit CPUs (Intel, ARM & MIPS).
32 *
31 * NDK r8d: Add android_setCpu(). 33 * NDK r8d: Add android_setCpu().
32 * 34 *
33 * NDK r8c: Add new ARM CPU features: VFPv2, VFP_D32, VFP_FP16, 35 * NDK r8c: Add new ARM CPU features: VFPv2, VFP_D32, VFP_FP16,
34 * VFP_FMA, NEON_FMA, IDIV_ARM, IDIV_THUMB2 and iWMMXt. 36 * VFP_FMA, NEON_FMA, IDIV_ARM, IDIV_THUMB2 and iWMMXt.
35 * 37 *
36 * Rewrite the code to parse /proc/self/auxv instead of 38 * Rewrite the code to parse /proc/self/auxv instead of
37 * the "Features" field in /proc/cpuinfo. 39 * the "Features" field in /proc/cpuinfo.
38 * 40 *
39 * Dynamically allocate the buffer that hold the content 41 * Dynamically allocate the buffer that hold the content
40 * of /proc/cpuinfo to deal with newer hardware. 42 * of /proc/cpuinfo to deal with newer hardware.
41 * 43 *
42 * NDK r7c: Fix CPU count computation. The old method only reported the 44 * NDK r7c: Fix CPU count computation. The old method only reported the
43 * number of _active_ CPUs when the library was initialized, 45 * number of _active_ CPUs when the library was initialized,
44 * which could be less than the real total. 46 * which could be less than the real total.
45 * 47 *
46 * NDK r5: Handle buggy kernels which report a CPU Architecture number of 7 48 * NDK r5: Handle buggy kernels which report a CPU Architecture number of 7
47 * for an ARMv6 CPU (see below). 49 * for an ARMv6 CPU (see below).
48 * 50 *
49 * Handle kernels that only report 'neon', and not 'vfpv3' 51 * Handle kernels that only report 'neon', and not 'vfpv3'
50 * (VFPv3 is mandated by the ARM architecture is Neon is implemented) 52 * (VFPv3 is mandated by the ARM architecture is Neon is implemented)
51 * 53 *
52 * Handle kernels that only report 'vfpv3d16', and not 'vfpv3' 54 * Handle kernels that only report 'vfpv3d16', and not 'vfpv3'
53 * 55 *
54 * Fix x86 compilation. Report ANDROID_CPU_FAMILY_X86 in 56 * Fix x86 compilation. Report ANDROID_CPU_FAMILY_X86 in
55 * android_getCpuFamily(). 57 * android_getCpuFamily().
56 * 58 *
57 * NDK r4: Initial release 59 * NDK r4: Initial release
58 */ 60 */
59 #include <sys/system_properties.h> 61
60 #ifdef __arm__ 62 #if defined(__le32__) || defined(__le64__)
61 #include <machine/cpu-features.h> 63
62 #endif 64 // When users enter this, we should only provide interface and
65 // libportable will give the implementations.
66
67 #else // !__le32__ && !__le64__
68
69 #include "cpu-features.h"
70
71 #include <dlfcn.h>
72 #include <errno.h>
73 #include <fcntl.h>
63 #include <pthread.h> 74 #include <pthread.h>
64 #include "cpu-features.h"
65 #include <stdio.h> 75 #include <stdio.h>
66 #include <stdlib.h> 76 #include <stdlib.h>
67 #include <fcntl.h> 77 #include <sys/system_properties.h>
68 #include <errno.h>
69 78
70 static pthread_once_t g_once; 79 static pthread_once_t g_once;
71 static int g_inited; 80 static int g_inited;
72 static AndroidCpuFamily g_cpuFamily; 81 static AndroidCpuFamily g_cpuFamily;
73 static uint64_t g_cpuFeatures; 82 static uint64_t g_cpuFeatures;
74 static int g_cpuCount; 83 static int g_cpuCount;
75 84
76 static const int android_cpufeatures_debug = 0; 85 #ifdef __arm__
86 static uint32_t g_cpuIdArm;
87 #endif
77 88
78 #ifdef __arm__ 89 static const int android_cpufeatures_debug = 0;
79 # define DEFAULT_CPU_FAMILY ANDROID_CPU_FAMILY_ARM
80 #elif defined __i386__
81 # define DEFAULT_CPU_FAMILY ANDROID_CPU_FAMILY_X86
82 #else
83 # define DEFAULT_CPU_FAMILY ANDROID_CPU_FAMILY_UNKNOWN
84 #endif
85 90
86 #define D(...) \ 91 #define D(...) \
87 do { \ 92 do { \
88 if (android_cpufeatures_debug) { \ 93 if (android_cpufeatures_debug) { \
89 printf(__VA_ARGS__); fflush(stdout); \ 94 printf(__VA_ARGS__); fflush(stdout); \
90 } \ 95 } \
91 } while (0) 96 } while (0)
92 97
93 #ifdef __i386__ 98 #ifdef __i386__
94 static __inline__ void x86_cpuid(int func, int values[4]) 99 static __inline__ void x86_cpuid(int func, int values[4])
(...skipping 21 matching lines...) Expand all
116 * using fseek(0, SEEK_END) + ftell(). Nor can they be mmap()-ed. 121 * using fseek(0, SEEK_END) + ftell(). Nor can they be mmap()-ed.
117 */ 122 */
118 static int 123 static int
119 get_file_size(const char* pathname) 124 get_file_size(const char* pathname)
120 { 125 {
121 int fd, ret, result = 0; 126 int fd, ret, result = 0;
122 char buffer[256]; 127 char buffer[256];
123 128
124 fd = open(pathname, O_RDONLY); 129 fd = open(pathname, O_RDONLY);
125 if (fd < 0) { 130 if (fd < 0) {
126 D("Can't open %s: %s\n", pathname, strerror(errno)); 131 D("Can't open %s: %s\n", pathname, strerror(errno));
127 return -1; 132 return -1;
128 } 133 }
129 134
130 for (;;) { 135 for (;;) {
131 int ret = read(fd, buffer, sizeof buffer); 136 int ret = read(fd, buffer, sizeof buffer);
132 if (ret < 0) { 137 if (ret < 0) {
133 if (errno == EINTR) 138 if (errno == EINTR)
134 continue; 139 continue;
135 D("Error while reading %s: %s\n", pathname, strerror(errno)); 140 D("Error while reading %s: %s\n", pathname, strerror(errno));
136 break; 141 break;
137 } 142 }
138 if (ret == 0) 143 if (ret == 0)
139 break; 144 break;
140 145
141 result += ret; 146 result += ret;
142 } 147 }
143 close(fd); 148 close(fd);
144 return result; 149 return result;
145 } 150 }
146 151
147 /* Read the content of /proc/cpuinfo into a user-provided buffer. 152 /* Read the content of /proc/cpuinfo into a user-provided buffer.
148 * Return the length of the data, or -1 on error. Does *not* 153 * Return the length of the data, or -1 on error. Does *not*
149 * zero-terminate the content. Will not read more 154 * zero-terminate the content. Will not read more
150 * than 'buffsize' bytes. 155 * than 'buffsize' bytes.
151 */ 156 */
(...skipping 26 matching lines...) Expand all
178 return count; 183 return count;
179 } 184 }
180 185
181 /* Extract the content of a the first occurence of a given field in 186 /* Extract the content of a the first occurence of a given field in
182 * the content of /proc/cpuinfo and return it as a heap-allocated 187 * the content of /proc/cpuinfo and return it as a heap-allocated
183 * string that must be freed by the caller. 188 * string that must be freed by the caller.
184 * 189 *
185 * Return NULL if not found 190 * Return NULL if not found
186 */ 191 */
187 static char* 192 static char*
188 extract_cpuinfo_field(char* buffer, int buflen, const char* field) 193 extract_cpuinfo_field(const char* buffer, int buflen, const char* field)
189 { 194 {
190 int fieldlen = strlen(field); 195 int fieldlen = strlen(field);
191 char* bufend = buffer + buflen; 196 const char* bufend = buffer + buflen;
192 char* result = NULL; 197 char* result = NULL;
193 int len, ignore; 198 int len, ignore;
194 const char *p, *q; 199 const char *p, *q;
195 200
196 /* Look for first field occurence, and ensures it starts the line. */ 201 /* Look for first field occurence, and ensures it starts the line. */
197 p = buffer; 202 p = buffer;
198 bufend = buffer + buflen;
199 for (;;) { 203 for (;;) {
200 p = memmem(p, bufend-p, field, fieldlen); 204 p = memmem(p, bufend-p, field, fieldlen);
201 if (p == NULL) 205 if (p == NULL)
202 goto EXIT; 206 goto EXIT;
203 207
204 if (p == buffer || p[-1] == '\n') 208 if (p == buffer || p[-1] == '\n')
205 break; 209 break;
206 210
207 p += fieldlen; 211 p += fieldlen;
208 } 212 }
(...skipping 16 matching lines...) Expand all
225 if (result == NULL) 229 if (result == NULL)
226 goto EXIT; 230 goto EXIT;
227 231
228 memcpy(result, p, len); 232 memcpy(result, p, len);
229 result[len] = '\0'; 233 result[len] = '\0';
230 234
231 EXIT: 235 EXIT:
232 return result; 236 return result;
233 } 237 }
234 238
235 /* Like strlen(), but for constant string literals */
236 #define STRLEN_CONST(x) ((sizeof(x)-1)
237
238
239 /* Checks that a space-separated list of items contains one given 'item'. 239 /* Checks that a space-separated list of items contains one given 'item'.
240 * Returns 1 if found, 0 otherwise. 240 * Returns 1 if found, 0 otherwise.
241 */ 241 */
242 static int 242 static int
243 has_list_item(const char* list, const char* item) 243 has_list_item(const char* list, const char* item)
244 { 244 {
245 const char* p = list; 245 const char* p = list;
246 int itemlen = strlen(item); 246 int itemlen = strlen(item);
247 247
248 if (list == NULL) 248 if (list == NULL)
(...skipping 13 matching lines...) Expand all
262 262
263 if (itemlen == q-p && !memcmp(p, item, itemlen)) 263 if (itemlen == q-p && !memcmp(p, item, itemlen))
264 return 1; 264 return 1;
265 265
266 /* skip to next item */ 266 /* skip to next item */
267 p = q; 267 p = q;
268 } 268 }
269 return 0; 269 return 0;
270 } 270 }
271 271
272 /* Parse an decimal integer starting from 'input', but not going further 272 /* Parse a number starting from 'input', but not going further
273 * than 'limit'. Return the value into '*result'. 273 * than 'limit'. Return the value into '*result'.
274 * 274 *
275 * NOTE: Does not skip over leading spaces, or deal with sign characters. 275 * NOTE: Does not skip over leading spaces, or deal with sign characters.
276 * NOTE: Ignores overflows. 276 * NOTE: Ignores overflows.
277 * 277 *
278 * The function returns NULL in case of error (bad format), or the new 278 * The function returns NULL in case of error (bad format), or the new
279 * position after the decimal number in case of success (which will always 279 * position after the decimal number in case of success (which will always
280 * be <= 'limit'). 280 * be <= 'limit').
281 */ 281 */
282 static const char* 282 static const char*
283 parse_decimal(const char* input, const char* limit, int* result) 283 parse_number(const char* input, const char* limit, int base, int* result)
284 { 284 {
285 const char* p = input; 285 const char* p = input;
286 int val = 0; 286 int val = 0;
287 while (p < limit) { 287 while (p < limit) {
288 int d = (*p - '0'); 288 int d = (*p - '0');
289 if ((unsigned)d >= 10U) 289 if ((unsigned)d >= 10U) {
290 break; 290 d = (*p - 'a');
291 val = val*10 + d; 291 if ((unsigned)d >= 6U)
292 d = (*p - 'A');
293 if ((unsigned)d >= 6U)
294 break;
295 d += 10;
296 }
297 if (d >= base)
298 break;
299 val = val*base + d;
292 p++; 300 p++;
293 } 301 }
294 if (p == input) 302 if (p == input)
295 return NULL; 303 return NULL;
296 304
297 *result = val; 305 *result = val;
298 return p; 306 return p;
299 } 307 }
300 308
309 static const char*
310 parse_decimal(const char* input, const char* limit, int* result)
311 {
312 return parse_number(input, limit, 10, result);
313 }
314
315 static const char*
316 parse_hexadecimal(const char* input, const char* limit, int* result)
317 {
318 return parse_number(input, limit, 16, result);
319 }
320
301 /* This small data type is used to represent a CPU list / mask, as read 321 /* This small data type is used to represent a CPU list / mask, as read
302 * from sysfs on Linux. See http://www.kernel.org/doc/Documentation/cputopology. txt 322 * from sysfs on Linux. See http://www.kernel.org/doc/Documentation/cputopology. txt
303 * 323 *
304 * For now, we don't expect more than 32 cores on mobile devices, so keep 324 * For now, we don't expect more than 32 cores on mobile devices, so keep
305 * everything simple. 325 * everything simple.
306 */ 326 */
307 typedef struct { 327 typedef struct {
308 uint32_t mask; 328 uint32_t mask;
309 } CpuList; 329 } CpuList;
310 330
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
401 cpulist_init(list); 421 cpulist_init(list);
402 422
403 filelen = read_file(filename, file, sizeof file); 423 filelen = read_file(filename, file, sizeof file);
404 if (filelen < 0) { 424 if (filelen < 0) {
405 D("Could not read %s: %s\n", filename, strerror(errno)); 425 D("Could not read %s: %s\n", filename, strerror(errno));
406 return; 426 return;
407 } 427 }
408 428
409 cpulist_parse(list, file, filelen); 429 cpulist_parse(list, file, filelen);
410 } 430 }
431 #if defined(__aarch64__)
432 // see <uapi/asm/hwcap.h> kernel header
433 #define HWCAP_FP (1 << 0)
434 #define HWCAP_ASIMD (1 << 1)
435 #define HWCAP_AES (1 << 3)
436 #define HWCAP_PMULL (1 << 4)
437 #define HWCAP_SHA1 (1 << 5)
438 #define HWCAP_SHA2 (1 << 6)
439 #define HWCAP_CRC32 (1 << 7)
440 #endif
441
442 #if defined(__arm__)
411 443
412 // See <asm/hwcap.h> kernel header. 444 // See <asm/hwcap.h> kernel header.
413 #define HWCAP_VFP (1 << 6) 445 #define HWCAP_VFP (1 << 6)
414 #define HWCAP_IWMMXT (1 << 9) 446 #define HWCAP_IWMMXT (1 << 9)
415 #define HWCAP_NEON (1 << 12) 447 #define HWCAP_NEON (1 << 12)
416 #define HWCAP_VFPv3 (1 << 13) 448 #define HWCAP_VFPv3 (1 << 13)
417 #define HWCAP_VFPv3D16 (1 << 14) 449 #define HWCAP_VFPv3D16 (1 << 14)
418 #define HWCAP_VFPv4 (1 << 16) 450 #define HWCAP_VFPv4 (1 << 16)
419 #define HWCAP_IDIVA (1 << 17) 451 #define HWCAP_IDIVA (1 << 17)
420 #define HWCAP_IDIVT (1 << 18) 452 #define HWCAP_IDIVT (1 << 18)
421 453
454 // see <uapi/asm/hwcap.h> kernel header
455 #define HWCAP2_AES (1 << 0)
456 #define HWCAP2_PMULL (1 << 1)
457 #define HWCAP2_SHA1 (1 << 2)
458 #define HWCAP2_SHA2 (1 << 3)
459 #define HWCAP2_CRC32 (1 << 4)
460
461 // This is the list of 32-bit ARMv7 optional features that are _always_
462 // supported by ARMv8 CPUs, as mandated by the ARM Architecture Reference
463 // Manual.
464 #define HWCAP_SET_FOR_ARMV8 \
465 ( HWCAP_VFP | \
466 HWCAP_NEON | \
467 HWCAP_VFPv3 | \
468 HWCAP_VFPv4 | \
469 HWCAP_IDIVA | \
470 HWCAP_IDIVT )
471 #endif
472
473 #if defined(__arm__) || defined(__aarch64__)
474
422 #define AT_HWCAP 16 475 #define AT_HWCAP 16
476 #define AT_HWCAP2 26
423 477
424 /* Read the ELF HWCAP flags by parsing /proc/self/auxv 478 // Probe the system's C library for a 'getauxval' function and call it if
425 */ 479 // it exits, or return 0 for failure. This function is available since API
480 // level 20.
481 //
482 // This code does *NOT* check for '__ANDROID_API__ >= 20' to support the
483 // edge case where some NDK developers use headers for a platform that is
484 // newer than the one really targetted by their application.
485 // This is typically done to use newer native APIs only when running on more
486 // recent Android versions, and requires careful symbol management.
487 //
488 // Note that getauxval() can't really be re-implemented here, because
489 // its implementation does not parse /proc/self/auxv. Instead it depends
490 // on values that are passed by the kernel at process-init time to the
491 // C runtime initialization layer.
426 static uint32_t 492 static uint32_t
427 get_elf_hwcap(void) 493 get_elf_hwcap_from_getauxval(int hwcap_type) {
428 { 494 typedef unsigned long getauxval_func_t(unsigned long);
429 uint32_t result = 0; 495
496 dlerror();
497 void* libc_handle = dlopen("libc.so", RTLD_NOW);
498 if (!libc_handle) {
499 D("Could not dlopen() C library: %s\n", dlerror());
500 return 0;
501 }
502
503 uint32_t ret = 0;
504 getauxval_func_t* func = (getauxval_func_t*)
505 dlsym(libc_handle, "getauxval");
506 if (!func) {
507 D("Could not find getauxval() in C library\n");
508 } else {
509 // Note: getauxval() returns 0 on failure. Doesn't touch errno.
510 ret = (uint32_t)(*func)(hwcap_type);
511 }
512 dlclose(libc_handle);
513 return ret;
514 }
515 #endif
516
517 #if defined(__arm__)
518 // Parse /proc/self/auxv to extract the ELF HW capabilities bitmap for the
519 // current CPU. Note that this file is not accessible from regular
520 // application processes on some Android platform releases.
521 // On success, return new ELF hwcaps, or 0 on failure.
522 static uint32_t
523 get_elf_hwcap_from_proc_self_auxv(void) {
430 const char filepath[] = "/proc/self/auxv"; 524 const char filepath[] = "/proc/self/auxv";
431 int fd = open(filepath, O_RDONLY); 525 int fd = TEMP_FAILURE_RETRY(open(filepath, O_RDONLY));
432 if (fd < 0) { 526 if (fd < 0) {
433 D("Could not open %s: %s\n", filepath, strerror(errno)); 527 D("Could not open %s: %s\n", filepath, strerror(errno));
434 return 0; 528 return 0;
435 } 529 }
436 530
437 struct { uint32_t tag; uint32_t value; } entry; 531 struct { uint32_t tag; uint32_t value; } entry;
438 532
533 uint32_t result = 0;
439 for (;;) { 534 for (;;) {
440 int ret = read(fd, (char*)&entry, sizeof entry); 535 int ret = TEMP_FAILURE_RETRY(read(fd, (char*)&entry, sizeof entry));
441 if (ret < 0) { 536 if (ret < 0) {
442 if (errno == EINTR)
443 continue;
444 D("Error while reading %s: %s\n", filepath, strerror(errno)); 537 D("Error while reading %s: %s\n", filepath, strerror(errno));
445 break; 538 break;
446 } 539 }
447 // Detect end of list. 540 // Detect end of list.
448 if (ret == 0 || (entry.tag == 0 && entry.value == 0)) 541 if (ret == 0 || (entry.tag == 0 && entry.value == 0))
449 break; 542 break;
450 if (entry.tag == AT_HWCAP) { 543 if (entry.tag == AT_HWCAP) {
451 result = entry.value; 544 result = entry.value;
452 break; 545 break;
453 } 546 }
454 } 547 }
455 close(fd); 548 close(fd);
456 return result; 549 return result;
457 } 550 }
458 551
552 /* Compute the ELF HWCAP flags from the content of /proc/cpuinfo.
553 * This works by parsing the 'Features' line, which lists which optional
554 * features the device's CPU supports, on top of its reference
555 * architecture.
556 */
557 static uint32_t
558 get_elf_hwcap_from_proc_cpuinfo(const char* cpuinfo, int cpuinfo_len) {
559 uint32_t hwcaps = 0;
560 long architecture = 0;
561 char* cpuArch = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "CPU architectur e");
562 if (cpuArch) {
563 architecture = strtol(cpuArch, NULL, 10);
564 free(cpuArch);
565
566 if (architecture >= 8L) {
567 // This is a 32-bit ARM binary running on a 64-bit ARM64 kernel.
568 // The 'Features' line only lists the optional features that the
569 // device's CPU supports, compared to its reference architecture
570 // which are of no use for this process.
571 D("Faking 32-bit ARM HWCaps on ARMv%ld CPU\n", architecture);
572 return HWCAP_SET_FOR_ARMV8;
573 }
574 }
575
576 char* cpuFeatures = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "Features");
577 if (cpuFeatures != NULL) {
578 D("Found cpuFeatures = '%s'\n", cpuFeatures);
579
580 if (has_list_item(cpuFeatures, "vfp"))
581 hwcaps |= HWCAP_VFP;
582 if (has_list_item(cpuFeatures, "vfpv3"))
583 hwcaps |= HWCAP_VFPv3;
584 if (has_list_item(cpuFeatures, "vfpv3d16"))
585 hwcaps |= HWCAP_VFPv3D16;
586 if (has_list_item(cpuFeatures, "vfpv4"))
587 hwcaps |= HWCAP_VFPv4;
588 if (has_list_item(cpuFeatures, "neon"))
589 hwcaps |= HWCAP_NEON;
590 if (has_list_item(cpuFeatures, "idiva"))
591 hwcaps |= HWCAP_IDIVA;
592 if (has_list_item(cpuFeatures, "idivt"))
593 hwcaps |= HWCAP_IDIVT;
594 if (has_list_item(cpuFeatures, "idiv"))
595 hwcaps |= HWCAP_IDIVA | HWCAP_IDIVT;
596 if (has_list_item(cpuFeatures, "iwmmxt"))
597 hwcaps |= HWCAP_IWMMXT;
598
599 free(cpuFeatures);
600 }
601 return hwcaps;
602 }
603
604 /* Check Houdini Binary Translator is installed on the system.
605 *
606 * If this function returns 1, get_elf_hwcap_from_getauxval() function
607 * will causes SIGSEGV while calling getauxval() function.
608 */
609 static int
610 has_houdini_binary_translator(void) {
611 int found = 0;
612 if (access("/system/lib/libhoudini.so", F_OK) != -1) {
613 D("Found Houdini binary translator\n");
614 found = 1;
615 }
616 return found;
617 }
618 #endif /* __arm__ */
619
459 /* Return the number of cpus present on a given device. 620 /* Return the number of cpus present on a given device.
460 * 621 *
461 * To handle all weird kernel configurations, we need to compute the 622 * To handle all weird kernel configurations, we need to compute the
462 * intersection of the 'present' and 'possible' CPU lists and count 623 * intersection of the 'present' and 'possible' CPU lists and count
463 * the result. 624 * the result.
464 */ 625 */
465 static int 626 static int
466 get_cpu_count(void) 627 get_cpu_count(void)
467 { 628 {
468 CpuList cpus_present[1]; 629 CpuList cpus_present[1];
469 CpuList cpus_possible[1]; 630 CpuList cpus_possible[1];
470 631
471 cpulist_read_from(cpus_present, "/sys/devices/system/cpu/present"); 632 cpulist_read_from(cpus_present, "/sys/devices/system/cpu/present");
472 cpulist_read_from(cpus_possible, "/sys/devices/system/cpu/possible"); 633 cpulist_read_from(cpus_possible, "/sys/devices/system/cpu/possible");
473 634
474 /* Compute the intersection of both sets to get the actual number of 635 /* Compute the intersection of both sets to get the actual number of
475 * CPU cores that can be used on this device by the kernel. 636 * CPU cores that can be used on this device by the kernel.
476 */ 637 */
477 cpulist_and(cpus_present, cpus_possible); 638 cpulist_and(cpus_present, cpus_possible);
478 639
479 return cpulist_count(cpus_present); 640 return cpulist_count(cpus_present);
480 } 641 }
481 642
482 static void 643 static void
483 android_cpuInitFamily(void) 644 android_cpuInitFamily(void)
484 { 645 {
485 #if defined(__ARM_ARCH__) 646 #if defined(__arm__)
486 g_cpuFamily = ANDROID_CPU_FAMILY_ARM; 647 g_cpuFamily = ANDROID_CPU_FAMILY_ARM;
487 #elif defined(__i386__) 648 #elif defined(__i386__)
488 g_cpuFamily = ANDROID_CPU_FAMILY_X86; 649 g_cpuFamily = ANDROID_CPU_FAMILY_X86;
489 #elif defined(_MIPS_ARCH) 650 #elif defined(__mips64)
651 /* Needs to be before __mips__ since the compiler defines both */
652 g_cpuFamily = ANDROID_CPU_FAMILY_MIPS64;
653 #elif defined(__mips__)
490 g_cpuFamily = ANDROID_CPU_FAMILY_MIPS; 654 g_cpuFamily = ANDROID_CPU_FAMILY_MIPS;
655 #elif defined(__aarch64__)
656 g_cpuFamily = ANDROID_CPU_FAMILY_ARM64;
657 #elif defined(__x86_64__)
658 g_cpuFamily = ANDROID_CPU_FAMILY_X86_64;
491 #else 659 #else
492 g_cpuFamily = ANDROID_CPU_FAMILY_UNKNOWN; 660 g_cpuFamily = ANDROID_CPU_FAMILY_UNKNOWN;
493 #endif 661 #endif
494 } 662 }
495 663
496 static void 664 static void
497 android_cpuInit(void) 665 android_cpuInit(void)
498 { 666 {
499 char* cpuinfo = NULL; 667 char* cpuinfo = NULL;
500 int cpuinfo_len; 668 int cpuinfo_len;
(...skipping 24 matching lines...) Expand all
525 } 693 }
526 694
527 /* Count the CPU cores, the value may be 0 for single-core CPUs */ 695 /* Count the CPU cores, the value may be 0 for single-core CPUs */
528 g_cpuCount = get_cpu_count(); 696 g_cpuCount = get_cpu_count();
529 if (g_cpuCount == 0) { 697 if (g_cpuCount == 0) {
530 g_cpuCount = 1; 698 g_cpuCount = 1;
531 } 699 }
532 700
533 D("found cpuCount = %d\n", g_cpuCount); 701 D("found cpuCount = %d\n", g_cpuCount);
534 702
535 #ifdef __ARM_ARCH__ 703 #ifdef __arm__
536 { 704 {
537 char* features = NULL;
538 char* architecture = NULL;
539
540 /* Extract architecture from the "CPU Architecture" field. 705 /* Extract architecture from the "CPU Architecture" field.
541 * The list is well-known, unlike the the output of 706 * The list is well-known, unlike the the output of
542 * the 'Processor' field which can vary greatly. 707 * the 'Processor' field which can vary greatly.
543 * 708 *
544 * See the definition of the 'proc_arch' array in 709 * See the definition of the 'proc_arch' array in
545 * $KERNEL/arch/arm/kernel/setup.c and the 'c_show' function in 710 * $KERNEL/arch/arm/kernel/setup.c and the 'c_show' function in
546 * same file. 711 * same file.
547 */ 712 */
548 char* cpuArch = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "CPU archite cture"); 713 char* cpuArch = extract_cpuinfo_field(cpuinfo, cpuinfo_len, "CPU archite cture");
549 714
550 if (cpuArch != NULL) { 715 if (cpuArch != NULL) {
551 char* end; 716 char* end;
552 long archNumber; 717 long archNumber;
553 int hasARMv7 = 0; 718 int hasARMv7 = 0;
554 719
555 D("found cpuArch = '%s'\n", cpuArch); 720 D("found cpuArch = '%s'\n", cpuArch);
556 721
557 /* read the initial decimal number, ignore the rest */ 722 /* read the initial decimal number, ignore the rest */
558 archNumber = strtol(cpuArch, &end, 10); 723 archNumber = strtol(cpuArch, &end, 10);
559 724
560 /* Here we assume that ARMv8 will be upwards compatible with v7 725 /* Note that ARMv8 is upwards compatible with ARMv7. */
561 * in the future. Unfortunately, there is no 'Features' field to
562 * indicate that Thumb-2 is supported.
563 */
564 if (end > cpuArch && archNumber >= 7) { 726 if (end > cpuArch && archNumber >= 7) {
565 hasARMv7 = 1; 727 hasARMv7 = 1;
566 } 728 }
567 729
568 /* Unfortunately, it seems that certain ARMv6-based CPUs 730 /* Unfortunately, it seems that certain ARMv6-based CPUs
569 * report an incorrect architecture number of 7! 731 * report an incorrect architecture number of 7!
570 * 732 *
571 * See http://code.google.com/p/android/issues/detail?id=10812 733 * See http://code.google.com/p/android/issues/detail?id=10812
572 * 734 *
573 * We try to correct this by looking at the 'elf_format' 735 * We try to correct this by looking at the 'elf_format'
(...skipping 19 matching lines...) Expand all
593 } 755 }
594 756
595 /* The LDREX / STREX instructions are available from ARMv6 */ 757 /* The LDREX / STREX instructions are available from ARMv6 */
596 if (archNumber >= 6) { 758 if (archNumber >= 6) {
597 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_LDREX_STREX; 759 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_LDREX_STREX;
598 } 760 }
599 761
600 free(cpuArch); 762 free(cpuArch);
601 } 763 }
602 764
765 /* Check Houdini binary translator is installed */
766 int has_houdini = has_houdini_binary_translator();
767
603 /* Extract the list of CPU features from ELF hwcaps */ 768 /* Extract the list of CPU features from ELF hwcaps */
604 uint32_t hwcaps = get_elf_hwcap(); 769 uint32_t hwcaps = 0;
770 if (!has_houdini) {
771 hwcaps = get_elf_hwcap_from_getauxval(AT_HWCAP);
772 }
773 if (!hwcaps) {
774 D("Parsing /proc/self/auxv to extract ELF hwcaps!\n");
775 hwcaps = get_elf_hwcap_from_proc_self_auxv();
776 }
777 if (!hwcaps) {
778 // Parsing /proc/self/auxv will fail from regular application
779 // processes on some Android platform versions, when this happens
780 // parse proc/cpuinfo instead.
781 D("Parsing /proc/cpuinfo to extract ELF hwcaps!\n");
782 hwcaps = get_elf_hwcap_from_proc_cpuinfo(cpuinfo, cpuinfo_len);
783 }
605 784
606 if (hwcaps != 0) { 785 if (hwcaps != 0) {
607 int has_vfp = (hwcaps & HWCAP_VFP); 786 int has_vfp = (hwcaps & HWCAP_VFP);
608 int has_vfpv3 = (hwcaps & HWCAP_VFPv3); 787 int has_vfpv3 = (hwcaps & HWCAP_VFPv3);
609 int has_vfpv3d16 = (hwcaps & HWCAP_VFPv3D16); 788 int has_vfpv3d16 = (hwcaps & HWCAP_VFPv3D16);
610 int has_vfpv4 = (hwcaps & HWCAP_VFPv4); 789 int has_vfpv4 = (hwcaps & HWCAP_VFPv4);
611 int has_neon = (hwcaps & HWCAP_NEON); 790 int has_neon = (hwcaps & HWCAP_NEON);
612 int has_idiva = (hwcaps & HWCAP_IDIVA); 791 int has_idiva = (hwcaps & HWCAP_IDIVA);
613 int has_idivt = (hwcaps & HWCAP_IDIVT); 792 int has_idivt = (hwcaps & HWCAP_IDIVT);
614 int has_iwmmxt = (hwcaps & HWCAP_IWMMXT); 793 int has_iwmmxt = (hwcaps & HWCAP_IWMMXT);
615 794
616 // The kernel does a poor job at ensuring consistency when 795 // The kernel does a poor job at ensuring consistency when
617 // describing CPU features. So lots of guessing is needed. 796 // describing CPU features. So lots of guessing is needed.
618 797
619 // 'vfpv4' implies VFPv3|VFP_FMA|FP16 798 // 'vfpv4' implies VFPv3|VFP_FMA|FP16
620 if (has_vfpv4) 799 if (has_vfpv4)
621 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3 | 800 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3 |
622 ANDROID_CPU_ARM_FEATURE_VFP_FP16 | 801 ANDROID_CPU_ARM_FEATURE_VFP_FP16 |
623 ANDROID_CPU_ARM_FEATURE_VFP_FMA; 802 ANDROID_CPU_ARM_FEATURE_VFP_FMA;
624 803
625 // 'vfpv3' or 'vfpv3d16' imply VFPv3. Note that unlike GCC, 804 // 'vfpv3' or 'vfpv3d16' imply VFPv3. Note that unlike GCC,
626 // a value of 'vfpv3' doesn't necessarily mean that the D32 805 // a value of 'vfpv3' doesn't necessarily mean that the D32
627 // feature is present, so be conservative. All CPUs in the 806 // feature is present, so be conservative. All CPUs in the
628 // field that support D32 also support NEON, so this should 807 // field that support D32 also support NEON, so this should
629 // not be a problem in practice. 808 // not be a problem in practice.
630 if (has_vfpv3 || has_vfpv3d16) 809 if (has_vfpv3 || has_vfpv3d16)
631 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3; 810 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3;
632 811
633 // 'vfp' is super ambiguous. Depending on the kernel, it can 812 // 'vfp' is super ambiguous. Depending on the kernel, it can
634 // either mean VFPv2 or VFPv3. Make it depend on ARMv7. 813 // either mean VFPv2 or VFPv3. Make it depend on ARMv7.
635 if (has_vfp) { 814 if (has_vfp) {
636 if (g_cpuFeatures & ANDROID_CPU_ARM_FEATURE_ARMv7) 815 if (g_cpuFeatures & ANDROID_CPU_ARM_FEATURE_ARMv7)
637 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3; 816 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3;
638 else 817 else
639 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2; 818 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2;
640 } 819 }
641 820
642 // Neon implies VFPv3|D32, and if vfpv4 is detected, NEON_FMA 821 // Neon implies VFPv3|D32, and if vfpv4 is detected, NEON_FMA
643 if (has_neon) { 822 if (has_neon) {
644 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3 | 823 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv3 |
645 ANDROID_CPU_ARM_FEATURE_NEON | 824 ANDROID_CPU_ARM_FEATURE_NEON |
646 ANDROID_CPU_ARM_FEATURE_VFP_D32; 825 ANDROID_CPU_ARM_FEATURE_VFP_D32;
647 if (has_vfpv4) 826 if (has_vfpv4)
648 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON_FMA; 827 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_NEON_FMA;
649 } 828 }
650 829
651 // VFPv3 implies VFPv2 and ARMv7 830 // VFPv3 implies VFPv2 and ARMv7
652 if (g_cpuFeatures & ANDROID_CPU_ARM_FEATURE_VFPv3) 831 if (g_cpuFeatures & ANDROID_CPU_ARM_FEATURE_VFPv3)
653 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2 | 832 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_VFPv2 |
654 ANDROID_CPU_ARM_FEATURE_ARMv7; 833 ANDROID_CPU_ARM_FEATURE_ARMv7;
655 834
656 // Note that some buggy kernels do not report these even when 835 if (has_idiva)
657 // the CPU actually support the division instructions. However, 836 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_ARM;
658 // assume that if 'vfpv4' is detected, then the CPU supports 837 if (has_idivt)
659 // sdiv/udiv properly. 838 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2;
660 if (has_idiva || has_vfpv4)
661 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_ARM;
662 if (has_idivt || has_vfpv4)
663 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2;
664 839
665 if (has_iwmmxt) 840 if (has_iwmmxt)
666 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_iWMMXt; 841 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_iWMMXt;
842 }
843
844 /* Extract the list of CPU features from ELF hwcaps2 */
845 uint32_t hwcaps2 = 0;
846 if (!has_houdini) {
847 hwcaps2 = get_elf_hwcap_from_getauxval(AT_HWCAP2);
848 }
849 if (hwcaps2 != 0) {
850 int has_aes = (hwcaps2 & HWCAP2_AES);
851 int has_pmull = (hwcaps2 & HWCAP2_PMULL);
852 int has_sha1 = (hwcaps2 & HWCAP2_SHA1);
853 int has_sha2 = (hwcaps2 & HWCAP2_SHA2);
854 int has_crc32 = (hwcaps2 & HWCAP2_CRC32);
855
856 if (has_aes)
857 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_AES;
858 if (has_pmull)
859 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_PMULL;
860 if (has_sha1)
861 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_SHA1;
862 if (has_sha2)
863 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_SHA2;
864 if (has_crc32)
865 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_CRC32;
866 }
867 /* Extract the cpuid value from various fields */
868 // The CPUID value is broken up in several entries in /proc/cpuinfo.
869 // This table is used to rebuild it from the entries.
870 static const struct CpuIdEntry {
871 const char* field;
872 char format;
873 char bit_lshift;
874 char bit_length;
875 } cpu_id_entries[] = {
876 { "CPU implementer", 'x', 24, 8 },
877 { "CPU variant", 'x', 20, 4 },
878 { "CPU part", 'x', 4, 12 },
879 { "CPU revision", 'd', 0, 4 },
880 };
881 size_t i;
882 D("Parsing /proc/cpuinfo to recover CPUID\n");
883 for (i = 0;
884 i < sizeof(cpu_id_entries)/sizeof(cpu_id_entries[0]);
885 ++i) {
886 const struct CpuIdEntry* entry = &cpu_id_entries[i];
887 char* value = extract_cpuinfo_field(cpuinfo,
888 cpuinfo_len,
889 entry->field);
890 if (value == NULL)
891 continue;
892
893 D("field=%s value='%s'\n", entry->field, value);
894 char* value_end = value + strlen(value);
895 int val = 0;
896 const char* start = value;
897 const char* p;
898 if (value[0] == '0' && (value[1] == 'x' || value[1] == 'X')) {
899 start += 2;
900 p = parse_hexadecimal(start, value_end, &val);
901 } else if (entry->format == 'x')
902 p = parse_hexadecimal(value, value_end, &val);
903 else
904 p = parse_decimal(value, value_end, &val);
905
906 if (p > (const char*)start) {
907 val &= ((1 << entry->bit_length)-1);
908 val <<= entry->bit_lshift;
909 g_cpuIdArm |= (uint32_t) val;
910 }
911
912 free(value);
913 }
914
915 // Handle kernel configuration bugs that prevent the correct
916 // reporting of CPU features.
917 static const struct CpuFix {
918 uint32_t cpuid;
919 uint64_t or_flags;
920 } cpu_fixes[] = {
921 /* The Nexus 4 (Qualcomm Krait) kernel configuration
922 * forgets to report IDIV support. */
923 { 0x510006f2, ANDROID_CPU_ARM_FEATURE_IDIV_ARM |
924 ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2 },
925 { 0x510006f3, ANDROID_CPU_ARM_FEATURE_IDIV_ARM |
926 ANDROID_CPU_ARM_FEATURE_IDIV_THUMB2 },
927 };
928 size_t n;
929 for (n = 0; n < sizeof(cpu_fixes)/sizeof(cpu_fixes[0]); ++n) {
930 const struct CpuFix* entry = &cpu_fixes[n];
931
932 if (g_cpuIdArm == entry->cpuid)
933 g_cpuFeatures |= entry->or_flags;
934 }
935
936 // Special case: The emulator-specific Android 4.2 kernel fails
937 // to report support for the 32-bit ARM IDIV instruction.
938 // Technically, this is a feature of the virtual CPU implemented
939 // by the emulator. Note that it could also support Thumb IDIV
940 // in the future, and this will have to be slightly updated.
941 char* hardware = extract_cpuinfo_field(cpuinfo,
942 cpuinfo_len,
943 "Hardware");
944 if (hardware) {
945 if (!strcmp(hardware, "Goldfish") &&
946 g_cpuIdArm == 0x4100c080 &&
947 (g_cpuFamily & ANDROID_CPU_ARM_FEATURE_ARMv7) != 0) {
948 g_cpuFeatures |= ANDROID_CPU_ARM_FEATURE_IDIV_ARM;
949 }
950 free(hardware);
667 } 951 }
668 } 952 }
669 #endif /* __ARM_ARCH__ */ 953 #endif /* __arm__ */
954 #ifdef __aarch64__
955 {
956 /* Extract the list of CPU features from ELF hwcaps */
957 uint32_t hwcaps = 0;
958 hwcaps = get_elf_hwcap_from_getauxval(AT_HWCAP);
959 if (hwcaps != 0) {
960 int has_fp = (hwcaps & HWCAP_FP);
961 int has_asimd = (hwcaps & HWCAP_ASIMD);
962 int has_aes = (hwcaps & HWCAP_AES);
963 int has_pmull = (hwcaps & HWCAP_PMULL);
964 int has_sha1 = (hwcaps & HWCAP_SHA1);
965 int has_sha2 = (hwcaps & HWCAP_SHA2);
966 int has_crc32 = (hwcaps & HWCAP_CRC32);
967
968 if(has_fp == 0) {
969 D("ERROR: Floating-point unit missing, but is required by Androi d on AArch64 CPUs\n");
970 }
971 if(has_asimd == 0) {
972 D("ERROR: ASIMD unit missing, but is required by Android on AArc h64 CPUs\n");
973 }
974
975 if (has_fp)
976 g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_FP;
977 if (has_asimd)
978 g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_ASIMD;
979 if (has_aes)
980 g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_AES;
981 if (has_pmull)
982 g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_PMULL;
983 if (has_sha1)
984 g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_SHA1;
985 if (has_sha2)
986 g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_SHA2;
987 if (has_crc32)
988 g_cpuFeatures |= ANDROID_CPU_ARM64_FEATURE_CRC32;
989 }
990 }
991 #endif /* __aarch64__ */
670 992
671 #ifdef __i386__ 993 #ifdef __i386__
672 int regs[4]; 994 int regs[4];
673 995
674 /* According to http://en.wikipedia.org/wiki/CPUID */ 996 /* According to http://en.wikipedia.org/wiki/CPUID */
675 #define VENDOR_INTEL_b 0x756e6547 997 #define VENDOR_INTEL_b 0x756e6547
676 #define VENDOR_INTEL_c 0x6c65746e 998 #define VENDOR_INTEL_c 0x6c65746e
677 #define VENDOR_INTEL_d 0x49656e69 999 #define VENDOR_INTEL_d 0x49656e69
678 1000
679 x86_cpuid(0, regs); 1001 x86_cpuid(0, regs);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
734 return 0; 1056 return 0;
735 1057
736 android_cpuInitFamily(); 1058 android_cpuInitFamily();
737 g_cpuCount = (cpu_count <= 0 ? 1 : cpu_count); 1059 g_cpuCount = (cpu_count <= 0 ? 1 : cpu_count);
738 g_cpuFeatures = cpu_features; 1060 g_cpuFeatures = cpu_features;
739 pthread_once(&g_once, android_cpuInitDummy); 1061 pthread_once(&g_once, android_cpuInitDummy);
740 1062
741 return 1; 1063 return 1;
742 } 1064 }
743 1065
1066 #ifdef __arm__
1067 uint32_t
1068 android_getCpuIdArm(void)
1069 {
1070 pthread_once(&g_once, android_cpuInit);
1071 return g_cpuIdArm;
1072 }
1073
1074 int
1075 android_setCpuArm(int cpu_count, uint64_t cpu_features, uint32_t cpu_id)
1076 {
1077 if (!android_setCpu(cpu_count, cpu_features))
1078 return 0;
1079
1080 g_cpuIdArm = cpu_id;
1081 return 1;
1082 }
1083 #endif /* __arm__ */
1084
744 /* 1085 /*
745 * Technical note: Making sense of ARM's FPU architecture versions. 1086 * Technical note: Making sense of ARM's FPU architecture versions.
746 * 1087 *
747 * FPA was ARM's first attempt at an FPU architecture. There is no Android 1088 * FPA was ARM's first attempt at an FPU architecture. There is no Android
748 * device that actually uses it since this technology was already obsolete 1089 * device that actually uses it since this technology was already obsolete
749 * when the project started. If you see references to FPA instructions 1090 * when the project started. If you see references to FPA instructions
750 * somewhere, you can be sure that this doesn't apply to Android at all. 1091 * somewhere, you can be sure that this doesn't apply to Android at all.
751 * 1092 *
752 * FPA was followed by "VFP", soon renamed "VFPv1" due to the emergence of 1093 * FPA was followed by "VFP", soon renamed "VFPv1" due to the emergence of
753 * new versions / additions to it. ARM considers this obsolete right now, 1094 * new versions / additions to it. ARM considers this obsolete right now,
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
918 * | 1259 * |
919 * +-------------------+ 1260 * +-------------------+
920 * | | 1261 * | |
921 * | ARCH_VFP_V3_FP16 (+EXT_FP16) 1262 * | ARCH_VFP_V3_FP16 (+EXT_FP16)
922 * | 1263 * |
923 * ARCH_VFP_V3_PLUS_NEON_V1 (+EXT_NEON) 1264 * ARCH_VFP_V3_PLUS_NEON_V1 (+EXT_NEON)
924 * | 1265 * |
925 * ARCH_NEON_FP16 (+EXT_FP16) 1266 * ARCH_NEON_FP16 (+EXT_FP16)
926 * 1267 *
927 */ 1268 */
1269
1270 #endif // defined(__le32__) || defined(__le64__)
OLDNEW
« no previous file with comments | « platform_tools/android/third_party/cpufeatures/cpu-features.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698