lmms
Cross-platform music production software
Toggle main menu visibility
Loading...
Searching...
No Matches
include
Hardware.h
Go to the documentation of this file.
1
/*
2
* Hardware.h - This file contains useful tools that are hardware-
3
* dependent, such as cache-line size and busy-wait hints.
4
*
5
* Copyright (c) 2026 Fawn Sannar <rubiefawn/at/gmail.com>
6
*
7
* This file is part of LMMS - https://lmms.io
8
*
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 2 of the License, or
12
* (at your option) any later version.
13
*
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
18
*
19
* You should have received a copy of the GNU General Public License along
20
* with this program; if not, write to the Free Software Foundation, Inc.,
21
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
*/
23
24
#ifndef LMMS_HARDWARE_H
25
#define LMMS_HARDWARE_H
26
27
#include <cstdint>
28
#include <new>
29
#if __cpp_lib_hardware_interference_size >= 201703L
30
#if defined(__GNUG__) && !defined(__clang__)
31
// https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#index-Winterference-size
32
#pragma GCC diagnostic ignored "-Winterference-size"
33
#endif
34
#endif
35
#include "lmmsconfig.h"
36
#if defined(LMMS_HOST_X86_64) || defined(LMMS_HOST_X86)
37
#include <immintrin.h>
38
#elif defined(LMMS_HOST_ARM64) || defined(LMMS_HOST_ARM32)
39
#if defined(__ARM_ACLE)
40
#include <arm_acle.h>
41
#elif defined(_MSC_VER)
42
#include <intrin.h>
43
#elif defined(__GNUG__)
// HACK: Remove this once GCC properly provides __ARM_ACLE
44
#if defined(LMMS_HOST_ARM64)
45
// https://developer.arm.com/documentation/ddi0602/2026-03/Base-Instructions/ISB--Instruction-synchronization-barrier-
46
// The parameter is ignored since 15 is the only valid value
47
inline
void
__isb(
unsigned
int
) {
asm
volatile
(
"isb 15"
:::
"memory"
); }
48
#elif defined(LMMS_HOST_ARM32)
49
inline
void
__yield() {
asm
volatile
(
"yield"
); }
50
#endif
51
#endif
52
#endif
53
54
namespace
lmms
55
{
56
60
inline
constexpr
std::size_t
hardware_destructive_interference_size
=
61
#if __cpp_lib_hardware_interference_size >= 201703L
62
std::hardware_destructive_interference_size;
63
#elif defined(LMMS_HOST_X86_64) || defined(LMMS_HOST_X86)
64
64;
65
#elif defined(LMMS_HOST_ARM64)
66
256;
67
#elif defined(LMMS_HOST_ARM32)
68
64;
69
#elif defined(LMMS_HOST_RISCV64) || defined(LMMS_HOST_RISCV32)
70
64;
71
#elif defined(LMMS_HOST_PPC64)
72
128;
73
#elif defined(LMMS_HOST_PPC32)
74
32;
75
#else
76
64;
77
#warning Defaulting to 64 for lmms::hardware_destructive_interference_size for this architecture. This may be incorrect.
78
#endif
79
80
81
89
inline
void
busyWaitHint
()
90
{
91
#if defined(LMMS_HOST_X86_64) || defined(LMMS_HOST_X86)
92
_mm_pause();
93
#elif defined(LMMS_HOST_ARM64)
94
__isb(15);
95
#elif defined(LMMS_HOST_ARM32)
96
__yield();
97
#elif defined(LMMS_HOST_RISCV64) || defined(LMMS_HOST_RISCV32)
98
asm
volatile
(
"pause"
);
99
#else
100
// TODO LMMS_HOST_PPC*
101
#warning lmms::busyWaitHint() is not implemented on this architecture and will have no effect. Performance may suffer.
102
#endif
103
}
104
105
106
113
inline
void
disableDenormals
()
114
{
115
#if defined(LMMS_HOST_X86_64) || defined(LMMS_HOST_X86)
116
// https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html
117
// IntelĀ® 64 and IA-32 Architectures Software Developer's Manual Volume 1: Basic Architecture
118
// 11.6.3 Checking for the DAZ Flag in the MXCSR Register
119
unsigned
int
flags = 0x8000;
// FTZ
120
alignas
(16) std::uint8_t buf[512] = {0};
121
#if defined(LMMS_HOST_X86_64)
122
_fxsave64(buf);
123
#elif defined(LMMS_HOST_X86)
124
_fxsave(buf);
125
#endif
126
flags |= buf[28] & 0x0040;
// DAZ if supported
127
_mm_setcsr(_mm_getcsr() | flags);
128
#elif defined(LMMS_HOST_ARM64) || defined(LMMS_HOST_ARM32)
129
constexpr
auto
FZ = 1 << 24;
// Flushing denormalized numbers to zero control bit
130
#if defined(_MSC_VER) && defined(LMMS_HOST_ARM64)
131
// https://learn.microsoft.com/en-us/cpp/intrinsics/arm64-intrinsics
132
// 0x5a20 == ARM64_SYSREG(0b11, 0b011, 0b0100, 0b0100, 0b000)
133
_WriteStatusReg(0x5a20, _ReadStatusReg(0x5a20) | FZ);
134
#elif defined(_MSC_VER) && defined(LMMS_HOST_ARM32)
135
// https://learn.microsoft.com/en-us/windows/arm/arm32-to-arm64
136
// https://learn.microsoft.com/en-us/windows/whats-new/deprecated-features
137
#warning MSVC for ARM32 is deprecated. lmms::disableDenormals() is not implemented and will have no effect.
138
#elif defined(LMMS_HOST_ARM64)
139
// https://developer.arm.com/documentation/ddi0601/2026-03/AArch64-Registers/FPCR--Floating-point-Control-Register
140
std::uint64_t fpcr;
141
asm
volatile
(
"mrs %0, fpcr"
:
"=r"
(fpcr));
142
asm
volatile
(
"msr fpcr, %0"
::
"ri"
(fpcr | FZ));
143
#elif defined(LMMS_HOST_ARM32)
144
// https://developer.arm.com/documentation/ddi0601/2026-03/AArch32-Registers/FPSCR--Floating-Point-Status-and-Control-Register
145
std::uint32_t fpscr;
146
asm
volatile
(
"vmrs %0, fpscr"
:
"=r"
(fpscr));
147
asm
volatile
(
"vmsr fpscr, %0"
::
"ri"
(fpscr | FZ));
148
#endif
149
#else
150
// TODO LMMS_HOST_RISCV*: https://docs.riscv.org/reference/isa/unpriv/f-st-ext.html
151
// As of v2.2 of both the F and D extensions, there appears to be no
152
// way to flush denormals to zero. This may change in the future.
153
// TODO LMMS_HOST_PPC*: https://openpowerfoundation.org/specifications/isa
154
// This is possible for SIMD instructions by setting bit 111 of the
155
// VSCR register (a.k.a. the "NJ" flag), but there doesn't appear to
156
// be an equivalent for scalar instructions?
157
#warning lmms::disableDenormals() is not implemented on this architecture and will have no effect. Performance may suffer.
158
#endif
159
}
160
161
}
// namespace lmms
162
163
#endif
// LMMS_HARDWARE_H
lmms
Definition
RemotePluginBase.cpp:34
lmms::busyWaitHint
void busyWaitHint()
Platform-dependent hint to the processor that it is in a busy-wait loop. This helps optimize spinlock...
Definition
Hardware.h:89
lmms::disableDenormals
void disableDenormals()
Disable IEEE 754 denormals on the current thread.
Definition
Hardware.h:113
lmms::hardware_destructive_interference_size
constexpr std::size_t hardware_destructive_interference_size
Platform-dependent minimum amount of padding between objects to prevent false cache sharing.
Definition
Hardware.h:60
Generated on
for lmms by
1.18.0