2023-02-08 18:12:00 +01:00
|
|
|
/* Spa */
|
|
|
|
|
/* SPDX-FileCopyrightText: Copyright © 2019 Wim Taymans */
|
|
|
|
|
/* SPDX-License-Identifier: MIT */
|
2019-02-08 17:48:58 +02:00
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
|
2021-05-18 11:40:50 +10:00
|
|
|
#include <spa/utils/string.h>
|
|
|
|
|
|
2019-02-08 17:48:58 +02:00
|
|
|
#define MAX_BUFFER 4096
|
|
|
|
|
|
|
|
|
|
static char *get_cpuinfo_line(char *cpuinfo, const char *tag)
|
|
|
|
|
{
|
|
|
|
|
char *line, *end, *colon;
|
|
|
|
|
|
|
|
|
|
if (!(line = strstr(cpuinfo, tag)))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
if (!(end = strchr(line, '\n')))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
if (!(colon = strchr(line, ':')))
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
if (++colon >= end)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
return strndup(colon, end - colon);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
arm_init(struct impl *impl)
|
|
|
|
|
{
|
|
|
|
|
uint32_t flags = 0;
|
2023-01-12 12:20:30 +01:00
|
|
|
char *cpuinfo, *line, buffer[MAX_BUFFER];
|
2019-02-08 17:48:58 +02:00
|
|
|
int arch;
|
|
|
|
|
|
2023-01-12 12:20:30 +01:00
|
|
|
if (!(cpuinfo = spa_cpu_read_file("/proc/cpuinfo", buffer, sizeof(buffer)))) {
|
2021-09-30 11:12:27 +02:00
|
|
|
spa_log_warn(impl->log, "%p: Can't read cpuinfo", impl);
|
2019-02-08 17:48:58 +02:00
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((line = get_cpuinfo_line(cpuinfo, "CPU architecture"))) {
|
|
|
|
|
arch = strtoul(line, NULL, 0);
|
|
|
|
|
if (arch >= 6)
|
|
|
|
|
flags |= SPA_CPU_FLAG_ARMV6;
|
|
|
|
|
if (arch >= 8)
|
|
|
|
|
flags |= SPA_CPU_FLAG_ARMV8;
|
|
|
|
|
|
|
|
|
|
free(line);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((line = get_cpuinfo_line(cpuinfo, "Features"))) {
|
2019-06-07 17:16:02 +02:00
|
|
|
char *state = NULL;
|
2019-02-08 17:48:58 +02:00
|
|
|
char *current = strtok_r(line, " ", &state);
|
|
|
|
|
|
|
|
|
|
do {
|
|
|
|
|
#if defined (__aarch64__)
|
2021-05-18 11:40:50 +10:00
|
|
|
if (spa_streq(current, "asimd"))
|
2019-02-08 17:48:58 +02:00
|
|
|
flags |= SPA_CPU_FLAG_NEON;
|
2021-05-18 11:40:50 +10:00
|
|
|
else if (spa_streq(current, "fp"))
|
2019-02-08 17:48:58 +02:00
|
|
|
flags |= SPA_CPU_FLAG_VFPV3 | SPA_CPU_FLAG_VFP;
|
|
|
|
|
#else
|
2021-05-18 11:40:50 +10:00
|
|
|
if (spa_streq(current, "vfp"))
|
2019-02-08 17:48:58 +02:00
|
|
|
flags |= SPA_CPU_FLAG_VFP;
|
2021-05-18 11:40:50 +10:00
|
|
|
else if (spa_streq(current, "neon"))
|
2019-02-08 17:48:58 +02:00
|
|
|
flags |= SPA_CPU_FLAG_NEON;
|
2021-05-18 11:40:50 +10:00
|
|
|
else if (spa_streq(current, "vfpv3"))
|
2019-02-08 17:48:58 +02:00
|
|
|
flags |= SPA_CPU_FLAG_VFPV3;
|
|
|
|
|
#endif
|
|
|
|
|
} while ((current = strtok_r(NULL, " ", &state)));
|
|
|
|
|
|
|
|
|
|
free(line);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl->flags = flags;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2021-10-11 14:54:48 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
static int arm_zero_denormals(void *object, bool enable)
|
|
|
|
|
{
|
|
|
|
|
#if defined(__aarch64__)
|
|
|
|
|
uint64_t cw;
|
|
|
|
|
if (enable)
|
|
|
|
|
__asm__ __volatile__(
|
|
|
|
|
"mrs %0, fpcr \n"
|
|
|
|
|
"orr %0, %0, #0x1000000 \n"
|
|
|
|
|
"msr fpcr, %0 \n"
|
|
|
|
|
"isb \n"
|
|
|
|
|
: "=r"(cw)::"memory");
|
|
|
|
|
else
|
|
|
|
|
__asm__ __volatile__(
|
|
|
|
|
"mrs %0, fpcr \n"
|
|
|
|
|
"and %0, %0, #~0x1000000 \n"
|
|
|
|
|
"msr fpcr, %0 \n"
|
|
|
|
|
"isb \n"
|
|
|
|
|
: "=r"(cw)::"memory");
|
2021-10-25 16:32:16 +02:00
|
|
|
#elif (defined(__VFP_FP__) && !defined(__SOFTFP__))
|
2021-10-11 14:54:48 +02:00
|
|
|
uint32_t cw;
|
|
|
|
|
if (enable)
|
|
|
|
|
__asm__ __volatile__(
|
|
|
|
|
"vmrs %0, fpscr \n"
|
|
|
|
|
"orr %0, %0, #0x1000000 \n"
|
|
|
|
|
"vmsr fpscr, %0 \n"
|
|
|
|
|
: "=r"(cw)::"memory");
|
|
|
|
|
else
|
|
|
|
|
__asm__ __volatile__(
|
|
|
|
|
"vmrs %0, fpscr \n"
|
|
|
|
|
"and %0, %0, #~0x1000000 \n"
|
|
|
|
|
"vmsr fpscr, %0 \n"
|
|
|
|
|
: "=r"(cw)::"memory");
|
|
|
|
|
#endif
|
|
|
|
|
return 0;
|
|
|
|
|
}
|