-
Notifications
You must be signed in to change notification settings - Fork 20
/
init_linux_gcc_arm.hpp
64 lines (55 loc) · 1.47 KB
/
init_linux_gcc_arm.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
// Copyright (c) 2013 Steinwurf ApS
// All Rights Reserved
//
// Distributed under the "BSD License". See the accompanying LICENSE.rst file.
#pragma once
#include <cassert>
#include <cstdio>
#include <cstring>
#include <elf.h>
#include <fcntl.h>
#include <linux/auxvec.h>
#include <unistd.h>
#include "cpuinfo_impl.hpp"
namespace cpuid
{
inline namespace STEINWURF_CPUID_VERSION
{
/// @todo docs
void init_cpuinfo(cpuinfo::impl& info)
{
#if defined(__aarch64__)
// The Advanced SIMD (NEON) instruction set is required on AArch64
// (64-bit ARM). Note that /proc/cpuinfo will display "asimd" instead of
// "neon" in the Features list on a 64-bit ARM CPU.
info.m_has_neon = true;
#else
// Runtime detection of NEON is necessary on 32-bit ARM CPUs
//
// Follow recommendation from Cortex-A Series Programmer's guide
// in Section 20.1.7 Detecting NEON. The guide is available at
// Steinwurf's Google drive: steinwurf/technical/experimental/cpuid
auto cpufile = open("/proc/self/auxv", O_RDONLY);
assert(cpufile);
Elf32_auxv_t auxv;
if (cpufile >= 0)
{
const auto size_auxv_t = sizeof(Elf32_auxv_t);
while (read(cpufile, &auxv, size_auxv_t) == size_auxv_t)
{
if (auxv.a_type == AT_HWCAP)
{
info.m_has_neon = (auxv.a_un.a_val & 4096) != 0;
break;
}
}
close(cpufile);
}
else
{
info.m_has_neon = false;
}
#endif
}
}
}