From 2d42b9a44f1935ec16cb63420fc20e257b9be21b Mon Sep 17 00:00:00 2001 From: hogliux Date: Wed, 19 Oct 2022 13:25:33 +0200 Subject: [PATCH] Windows: Added Windows ARM support to JUCE --- .../ProjectSaving/jucer_ProjectExport_MSVC.h | 52 +++--- .../buffers/juce_FloatVectorOperations.cpp | 55 ++++--- .../buffers/juce_FloatVectorOperations.h | 2 +- .../codecs/oggvorbis/libvorbis-1.3.7/lib/os.h | 4 +- .../native/juce_win32_SystemStats.cpp | 153 +++++++++++++----- .../juce_core/system/juce_TargetPlatform.h | 6 +- modules/juce_dsp/juce_dsp.cpp | 4 +- modules/juce_dsp/juce_dsp.h | 6 +- 8 files changed, 189 insertions(+), 93 deletions(-) diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h index d79e82f2ec..86f6310d53 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h @@ -171,7 +171,7 @@ public: multiProcessorCompilationValue (config, Ids::multiProcessorCompilation, getUndoManager(), true), intermediatesPathValue (config, Ids::intermediatesPath, getUndoManager()), characterSetValue (config, Ids::characterSet, getUndoManager()), - architectureTypeValue (config, Ids::winArchitecture, getUndoManager(), get64BitArchName()), + architectureTypeValue (config, Ids::winArchitecture, getUndoManager(), getIntel64BitArchName()), fastMathValue (config, Ids::fastMath, getUndoManager()), debugInformationFormatValue (config, Ids::debugInformationFormat, getUndoManager(), isDebug() ? "ProgramDatabase" : "None"), pluginBinaryCopyStepValue (config, Ids::enablePluginBinaryCopyStep, getUndoManager(), false), @@ -201,8 +201,10 @@ public: String getUnityPluginBinaryLocationString() const { return unityPluginBinaryLocation.get(); } String getIntermediatesPathString() const { return intermediatesPathValue.get(); } String getCharacterSetString() const { return characterSetValue.get(); } - String get64BitArchName() const { return "x64"; } - String get32BitArchName() const { return "Win32"; } + String getIntel64BitArchName() const { return "x64"; } + String getIntel32BitArchName() const { return "Win32"; } + String getArm64BitArchName() const { return "ARM64"; } + String getArm32BitArchName() const { return "ARM"; } String getArchitectureString() const { return architectureTypeValue.get(); } String getDebugInformationFormatString() const { return debugInformationFormatValue.get(); } @@ -211,14 +213,13 @@ public: bool shouldLinkIncremental() const { return enableIncrementalLinkingValue.get(); } bool isUsingRuntimeLibDLL() const { return useRuntimeLibDLLValue.get(); } bool shouldUseMultiProcessorCompilation() const { return multiProcessorCompilationValue.get(); } - bool is64Bit() const { return getArchitectureString() == get64BitArchName(); } bool isFastMathEnabled() const { return fastMathValue.get(); } bool isPluginBinaryCopyStepEnabled() const { return pluginBinaryCopyStepValue.get(); } //============================================================================== String createMSVCConfigName() const { - return getName() + "|" + (is64Bit() ? "x64" : "Win32"); + return getName() + "|" + getArchitectureString(); } String getOutputFilename (const String& suffix, @@ -245,10 +246,9 @@ public: addVisualStudioPluginInstallPathProperties (props); props.add (new ChoicePropertyComponent (architectureTypeValue, "Architecture", - { get32BitArchName(), get64BitArchName() }, - { get32BitArchName(), get64BitArchName() }), - "Whether to use a 32-bit or 64-bit architecture."); - + { getIntel32BitArchName(), getIntel64BitArchName(), getArm32BitArchName(), getArm64BitArchName() }, + { getIntel32BitArchName(), getIntel64BitArchName(), getArm32BitArchName(), getArm64BitArchName() }), + "Which Windows architecture to use."); props.add (new ChoicePropertyComponentWithEnablement (debugInformationFormatValue, isDebug() ? isDebugValue : generateDebugSymbolsValue, @@ -384,13 +384,26 @@ public: void setPluginBinaryCopyLocationDefaults() { - vstBinaryLocation.setDefault ((is64Bit() ? "%ProgramW6432%" : "%programfiles(x86)%") + String ("\\Steinberg\\Vstplugins")); + const auto [programsFolderPath, commonsFolderPath] = [&]() -> std::tuple + { + static const std::map> options + { + { "Win32", { "%programfiles(x86)%", "%CommonProgramFiles(x86)%" } }, + { "x64", { "%ProgramW6432%", "%CommonProgramW6432%" } }, + { "ARM", { "%programfiles(arm)%", "%CommonProgramFiles(arm)%" } }, + { "ARM64", { "%ProgramW6432%", "%CommonProgramW6432%" } } + }; - auto prefix = is64Bit() ? "%CommonProgramW6432%" - : "%CommonProgramFiles(x86)%"; + if (const auto iter = options.find (getArchitectureString()); iter != options.cend()) + return iter->second; - vst3BinaryLocation.setDefault (prefix + String ("\\VST3")); - aaxBinaryLocation.setDefault (prefix + String ("\\Avid\\Audio\\Plug-Ins")); + jassertfalse; + return { "%programfiles%", "%CommonProgramFiles%" }; + }(); + + vstBinaryLocation.setDefault (programsFolderPath + String ("\\Steinberg\\Vstplugins")); + vst3BinaryLocation.setDefault (commonsFolderPath + String ("\\VST3")); + aaxBinaryLocation.setDefault (commonsFolderPath + String ("\\Avid\\Audio\\Plug-Ins")); lv2BinaryLocation.setDefault ("%APPDATA%\\LV2"); } @@ -434,8 +447,7 @@ public: auto* e = configsGroup->createNewChildElement ("ProjectConfiguration"); e->setAttribute ("Include", config.createMSVCConfigName()); e->createNewChildElement ("Configuration")->addTextElement (config.getName()); - e->createNewChildElement ("Platform")->addTextElement (config.is64Bit() ? config.get64BitArchName() - : config.get32BitArchName()); + e->createNewChildElement ("Platform")->addTextElement (config.getArchitectureString()); } } @@ -662,7 +674,7 @@ public: link->createNewChildElement ("ProgramDatabaseFile")->addTextElement (pdbFilename); link->createNewChildElement ("SubSystem")->addTextElement (type == ConsoleApp || type == LV2TurtleProgram ? "Console" : "Windows"); - if (! config.is64Bit()) + if (config.getArchitectureString() == "Win32") link->createNewChildElement ("TargetMachine")->addTextElement ("MachineX86"); if (isUsingEditAndContinue) @@ -727,7 +739,7 @@ public: build_tools::RelativePath::buildTargetFolder).toWindowsStyle()); } - if (getTargetFileType() == staticLibrary && ! config.is64Bit()) + if (getTargetFileType() == staticLibrary && config.getArchitectureString() == "Win32") { auto* lib = group->createNewChildElement ("Lib"); lib->createNewChildElement ("TargetMachine")->addTextElement ("MachineX86"); @@ -1207,7 +1219,7 @@ public: auto outputFilename = config.getOutputFilename (".aaxplugin", true, type); auto bundleDir = getOwner().getOutDirFile (config, outputFilename); auto bundleContents = bundleDir + "\\Contents"; - auto archDir = bundleContents + String ("\\") + (config.is64Bit() ? "x64" : "Win32"); + auto archDir = bundleContents + String ("\\") + config.getArchitectureString(); auto executablePath = archDir + String ("\\") + outputFilename; auto pkgScript = String ("copy /Y ") + getOutputFilePath (config).quoted() + String (" ") + executablePath.quoted() + String ("\r\ncall ") @@ -1285,7 +1297,7 @@ public: auto bundleDir = getOwner().getOutDirFile (config, config.getOutputFilename (".aaxplugin", false, type)); auto bundleContents = bundleDir + "\\Contents"; - auto archDir = bundleContents + String ("\\") + (config.is64Bit() ? "x64" : "Win32"); + auto archDir = bundleContents + String ("\\") + config.getArchitectureString(); for (auto& folder : StringArray { bundleDir, bundleContents, archDir }) script += String ("if not exist \"") + folder + String ("\" mkdir \"") + folder + String ("\"\r\n"); diff --git a/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp b/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp index 1e5af0e638..d65a8f257a 100644 --- a/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp +++ b/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp @@ -1430,34 +1430,44 @@ void JUCE_CALLTYPE FloatVectorOperations::convertFixedToFloat (float* dest, cons intptr_t JUCE_CALLTYPE FloatVectorOperations::getFpStatusRegister() noexcept { intptr_t fpsr = 0; - #if JUCE_INTEL && JUCE_USE_SSE_INTRINSICS + #if JUCE_INTEL && JUCE_USE_SSE_INTRINSICS fpsr = static_cast (_mm_getcsr()); - #elif defined(__arm64__) || defined(__aarch64__) || JUCE_USE_ARM_NEON - #if defined(__arm64__) || defined(__aarch64__) + #elif (JUCE_64BIT && JUCE_ARM) || JUCE_USE_ARM_NEON + #if _MSC_VER + // _control87 returns static values for x86 bits that don't exist on arm + // to emulate x86 behaviour. We are only ever interested in de-normal bits + // so mask out only those. + fpsr = (intptr_t) (_control87 (0, 0) & _MCW_DN); + #else + #if JUCE_64BIT asm volatile("mrs %0, fpcr" : "=r"(fpsr)); #elif JUCE_USE_ARM_NEON asm volatile("vmrs %0, fpscr" : "=r"(fpsr)); #endif - #else - #if ! (defined(JUCE_INTEL) || defined(JUCE_ARM)) - jassertfalse; // No support for getting the floating point status register for your platform - #endif #endif + #else + #if ! (defined (JUCE_INTEL) || defined (JUCE_ARM)) + jassertfalse; // No support for getting the floating point status register for your platform + #endif + #endif return fpsr; } void JUCE_CALLTYPE FloatVectorOperations::setFpStatusRegister (intptr_t fpsr) noexcept { - #if JUCE_INTEL && JUCE_USE_SSE_INTRINSICS + #if JUCE_INTEL && JUCE_USE_SSE_INTRINSICS // the volatile keyword here is needed to workaround a bug in AppleClang 13.0 // which aggressively optimises away the variable otherwise volatile auto fpsr_w = static_cast (fpsr); _mm_setcsr (fpsr_w); - #elif defined(__arm64__) || defined(__aarch64__) || JUCE_USE_ARM_NEON - #if defined(__arm64__) || defined(__aarch64__) + #elif (JUCE_64BIT && JUCE_ARM) || JUCE_USE_ARM_NEON + #if _MSC_VER + _control87 ((unsigned int) fpsr, _MCW_DN); + #else + #if JUCE_64BIT asm volatile("msr fpcr, %0" : : "ri"(fpsr)); @@ -1466,17 +1476,18 @@ void JUCE_CALLTYPE FloatVectorOperations::setFpStatusRegister (intptr_t fpsr) no : : "ri"(fpsr)); #endif - #else - #if ! (defined(JUCE_INTEL) || defined(JUCE_ARM)) - jassertfalse; // No support for getting the floating point status register for your platform - #endif - ignoreUnused (fpsr); #endif + #else + #if ! (defined (JUCE_INTEL) || defined (JUCE_ARM)) + jassertfalse; // No support for getting the floating point status register for your platform + #endif + ignoreUnused (fpsr); + #endif } void JUCE_CALLTYPE FloatVectorOperations::enableFlushToZeroMode (bool shouldEnable) noexcept { - #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__)) + #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM)) #if JUCE_USE_SSE_INTRINSICS intptr_t mask = _MM_FLUSH_ZERO_MASK; #else /*JUCE_USE_ARM_NEON*/ @@ -1484,7 +1495,7 @@ void JUCE_CALLTYPE FloatVectorOperations::enableFlushToZeroMode (bool shouldEnab #endif setFpStatusRegister ((getFpStatusRegister() & (~mask)) | (shouldEnable ? mask : 0)); #else - #if ! (defined(JUCE_INTEL) || defined(JUCE_ARM)) + #if ! (defined (JUCE_INTEL) || defined (JUCE_ARM)) jassertfalse; // No support for flush to zero mode on your platform #endif ignoreUnused (shouldEnable); @@ -1493,7 +1504,7 @@ void JUCE_CALLTYPE FloatVectorOperations::enableFlushToZeroMode (bool shouldEnab void JUCE_CALLTYPE FloatVectorOperations::disableDenormalisedNumberSupport (bool shouldDisable) noexcept { - #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__)) + #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM)) #if JUCE_USE_SSE_INTRINSICS intptr_t mask = 0x8040; #else /*JUCE_USE_ARM_NEON*/ @@ -1504,7 +1515,7 @@ void JUCE_CALLTYPE FloatVectorOperations::disableDenormalisedNumberSupport (bool #else ignoreUnused (shouldDisable); - #if ! (defined(JUCE_INTEL) || defined(JUCE_ARM)) + #if ! (defined (JUCE_INTEL) || defined (JUCE_ARM)) jassertfalse; // No support for disable denormals mode on your platform #endif #endif @@ -1512,7 +1523,7 @@ void JUCE_CALLTYPE FloatVectorOperations::disableDenormalisedNumberSupport (bool bool JUCE_CALLTYPE FloatVectorOperations::areDenormalsDisabled() noexcept { - #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__)) + #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM)) #if JUCE_USE_SSE_INTRINSICS intptr_t mask = 0x8040; #else /*JUCE_USE_ARM_NEON*/ @@ -1527,7 +1538,7 @@ bool JUCE_CALLTYPE FloatVectorOperations::areDenormalsDisabled() noexcept ScopedNoDenormals::ScopedNoDenormals() noexcept { - #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__)) + #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM)) #if JUCE_USE_SSE_INTRINSICS intptr_t mask = 0x8040; #else /*JUCE_USE_ARM_NEON*/ @@ -1541,7 +1552,7 @@ ScopedNoDenormals::ScopedNoDenormals() noexcept ScopedNoDenormals::~ScopedNoDenormals() noexcept { - #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__)) + #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM)) FloatVectorOperations::setFpStatusRegister (fpsr); #endif } diff --git a/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h b/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h index 3f0f0366e7..cf7ae84a36 100644 --- a/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h +++ b/modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h @@ -261,7 +261,7 @@ public: ~ScopedNoDenormals() noexcept; private: - #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined (__arm64__) || defined (__aarch64__)) + #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM)) intptr_t fpsr; #endif }; diff --git a/modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/os.h b/modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/os.h index fc65b594f8..868857d69e 100644 --- a/modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/os.h +++ b/modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/os.h @@ -119,7 +119,7 @@ static inline int vorbis_ftoi(double f){ /* yes, double! Otherwise, /* MSVC inline assembly. 32 bit only; inline ASM isn't implemented in the * 64 bit compiler and doesn't work on arm. */ -#if defined(_MSC_VER) && defined(_M_IX86) && !defined(_WIN32_WCE) +#if (defined(_MSC_VER) && defined(_M_IX86) && !defined(_WIN32_WCE)) && (! JUCE_ARM) # define VORBIS_FPU_CONTROL typedef ogg_int16_t vorbis_fpu_control; @@ -146,7 +146,7 @@ static __inline void vorbis_fpu_restore(vorbis_fpu_control fpu){ /* Optimized code path for x86_64 builds. Uses SSE2 intrinsics. This can be done safely because all x86_64 CPUs supports SSE2. */ -#if ((JUCE_MSVC && JUCE_64BIT) || (JUCE_GCC && defined (__x86_64__))) +#if (((JUCE_MSVC && JUCE_64BIT) || (JUCE_GCC && defined (__x86_64__)))) && (! JUCE_ARM) # define VORBIS_FPU_CONTROL typedef ogg_int16_t vorbis_fpu_control; diff --git a/modules/juce_core/native/juce_win32_SystemStats.cpp b/modules/juce_core/native/juce_win32_SystemStats.cpp index 11f2be1d1c..23cfafba9e 100644 --- a/modules/juce_core/native/juce_win32_SystemStats.cpp +++ b/modules/juce_core/native/juce_win32_SystemStats.cpp @@ -23,11 +23,6 @@ namespace juce { -#if JUCE_MSVC && ! defined (__INTEL_COMPILER) - #pragma intrinsic (__cpuid) - #pragma intrinsic (__rdtsc) -#endif - void Logger::outputDebugString (const String& text) { OutputDebugString ((text + "\n").toWideCharPointer()); @@ -39,9 +34,50 @@ void Logger::outputDebugString (const String& text) JUCE_API void juceDLL_free (void* block) { std::free (block); } #endif -//============================================================================== +static int findNumberOfPhysicalCores() noexcept +{ + #if JUCE_MINGW + // Not implemented in MinGW + jassertfalse; -#if JUCE_MINGW || JUCE_CLANG + return 1; + #else + + DWORD bufferSize = 0; + GetLogicalProcessorInformation (nullptr, &bufferSize); + + const auto numBuffers = (size_t) (bufferSize / sizeof (SYSTEM_LOGICAL_PROCESSOR_INFORMATION)); + + if (numBuffers == 0) + { + jassertfalse; + return 0; + }; + + HeapBlock buffer (numBuffers); + + if (! GetLogicalProcessorInformation (buffer, &bufferSize)) + { + jassertfalse; + return 0; + } + + return (int) std::count_if (buffer.get(), buffer.get() + numBuffers, [] (const auto& info) + { + return info.Relationship == RelationProcessorCore; + }); + + #endif // JUCE_MINGW +} + +//============================================================================== +#if JUCE_INTEL + #if JUCE_MSVC && ! defined (__INTEL_COMPILER) + #pragma intrinsic (__cpuid) + #pragma intrinsic (__rdtsc) + #endif + + #if JUCE_MINGW || JUCE_CLANG static void callCPUID (int result[4], uint32 type) { uint32 la = (uint32) result[0], lb = (uint32) result[1], @@ -59,12 +95,12 @@ static void callCPUID (int result[4], uint32 type) result[0] = (int) la; result[1] = (int) lb; result[2] = (int) lc; result[3] = (int) ld; } -#else + #else static void callCPUID (int result[4], int infoType) { __cpuid (result, infoType); } -#endif + #endif String SystemStats::getCpuVendor() { @@ -103,34 +139,6 @@ String SystemStats::getCpuModel() return String (name).trim(); } -static int findNumberOfPhysicalCores() noexcept -{ - #if JUCE_MINGW - // Not implemented in MinGW - jassertfalse; - - return 1; - #else - - int numPhysicalCores = 0; - DWORD bufferSize = 0; - GetLogicalProcessorInformation (nullptr, &bufferSize); - - if (auto numBuffers = (size_t) (bufferSize / sizeof (SYSTEM_LOGICAL_PROCESSOR_INFORMATION))) - { - HeapBlock buffer (numBuffers); - - if (GetLogicalProcessorInformation (buffer, &bufferSize)) - for (size_t i = 0; i < numBuffers; ++i) - if (buffer[i].Relationship == RelationProcessorCore) - ++numPhysicalCores; - } - - return numPhysicalCores; - #endif // JUCE_MINGW -} - -//============================================================================== void CPUInformation::initialise() noexcept { int info[4] = { 0 }; @@ -176,6 +184,49 @@ void CPUInformation::initialise() noexcept if (numPhysicalCPUs <= 0) numPhysicalCPUs = numLogicalCPUs; } +#elif JUCE_ARM +String SystemStats::getCpuVendor() +{ + static const auto cpuVendor = [] + { + static constexpr auto* path = "HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\\VendorIdentifier"; + auto vendor = RegistryKeyWrapper::getValue (path, {}, 0).trim(); + + return vendor.isEmpty() ? String ("Unknown Vendor") : vendor; + }(); + + return cpuVendor; +} + +String SystemStats::getCpuModel() +{ + static const auto cpuModel = [] + { + static constexpr auto* path = "HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\\ProcessorNameString"; + auto model = RegistryKeyWrapper::getValue (path, {}, 0).trim(); + + return model.isEmpty() ? String ("Unknown Model") : model; + }(); + + return cpuModel; +} + +void CPUInformation::initialise() noexcept +{ + // Windows for arm requires at least armv7 which has neon support + hasNeon = true; + + SYSTEM_INFO systemInfo; + GetNativeSystemInfo (&systemInfo); + numLogicalCPUs = (int) systemInfo.dwNumberOfProcessors; + numPhysicalCPUs = findNumberOfPhysicalCores(); + + if (numPhysicalCPUs <= 0) + numPhysicalCPUs = numLogicalCPUs; +} +#else + #error Unknown CPU architecture type +#endif #if JUCE_MSVC && JUCE_CHECK_MEMORY_LEAKS struct DebugFlagsInitialiser @@ -442,11 +493,21 @@ double Time::getMillisecondCounterHiRes() noexcept { return hiResCounterHa //============================================================================== static int64 juce_getClockCycleCounter() noexcept { - #if JUCE_MSVC + #if JUCE_MSVC + #if JUCE_INTEL // MS intrinsics version... return (int64) __rdtsc(); - - #elif JUCE_GCC || JUCE_CLANG + #elif JUCE_ARM + #if defined (_M_ARM) + return __rdpmccntr64(); + #elif defined (_M_ARM64) + return _ReadStatusReg (ARM64_PMCCNTR_EL0); + #else + #error Unknown arm architecture + #endif + #endif + #elif JUCE_GCC || JUCE_CLANG + #if JUCE_INTEL // GNU inline asm version... unsigned int hi = 0, lo = 0; @@ -462,9 +523,15 @@ static int64 juce_getClockCycleCounter() noexcept : "cc", "eax", "ebx", "ecx", "edx", "memory"); return (int64) ((((uint64) hi) << 32) | lo); - #else - #error "unknown compiler?" - #endif + #elif JUCE_ARM + int64 retval; + + __asm__ __volatile__ ("mrs %0, cntvct_el0" : "=r"(retval)); + return retval; + #endif + #else + #error "unknown compiler?" + #endif } int SystemStats::getCpuSpeedInMegahertz() diff --git a/modules/juce_core/system/juce_TargetPlatform.h b/modules/juce_core/system/juce_TargetPlatform.h index aca2e65676..0b710e294e 100644 --- a/modules/juce_core/system/juce_TargetPlatform.h +++ b/modules/juce_core/system/juce_TargetPlatform.h @@ -109,7 +109,11 @@ /** If defined, this indicates that the processor is little-endian. */ #define JUCE_LITTLE_ENDIAN 1 - #define JUCE_INTEL 1 + #if defined (_M_ARM) || defined (_M_ARM64) || defined (__arm__) || defined (__aarch64__) + #define JUCE_ARM 1 + #else + #define JUCE_INTEL 1 + #endif #endif //============================================================================== diff --git a/modules/juce_dsp/juce_dsp.cpp b/modules/juce_dsp/juce_dsp.cpp index 40dd665f51..e939a6a867 100644 --- a/modules/juce_dsp/juce_dsp.cpp +++ b/modules/juce_dsp/juce_dsp.cpp @@ -79,13 +79,13 @@ #include "widgets/juce_Chorus.cpp" #if JUCE_USE_SIMD - #if defined(__i386__) || defined(__amd64__) || defined(_M_X64) || defined(_X86_) || defined(_M_IX86) + #if JUCE_INTEL #ifdef __AVX2__ #include "native/juce_avx_SIMDNativeOps.cpp" #else #include "native/juce_sse_SIMDNativeOps.cpp" #endif - #elif defined(__arm__) || defined(_M_ARM) || defined (__arm64__) || defined (__aarch64__) + #elif JUCE_ARM #include "native/juce_neon_SIMDNativeOps.cpp" #else #error "SIMD register support not implemented for this platform" diff --git a/modules/juce_dsp/juce_dsp.h b/modules/juce_dsp/juce_dsp.h index b2d5f404b0..560e29b68b 100644 --- a/modules/juce_dsp/juce_dsp.h +++ b/modules/juce_dsp/juce_dsp.h @@ -74,7 +74,9 @@ #include #endif -#elif defined (__ARM_NEON__) || defined (__ARM_NEON) || defined (__arm64__) || defined (__aarch64__) +// it's ok to check for _M_ARM below as this is only defined on Windows for Arm 32-bit +// which has a minimum requirement of armv7, which supports neon. +#elif defined (__ARM_NEON__) || defined (__ARM_NEON) || defined (__arm64__) || defined (__aarch64__) || defined (_M_ARM) || defined (_M_ARM64) #ifndef JUCE_USE_SIMD #define JUCE_USE_SIMD 1 @@ -227,7 +229,7 @@ namespace juce #else #include "native/juce_sse_SIMDNativeOps.h" #endif - #elif defined(__arm__) || defined(_M_ARM) || defined (__arm64__) || defined (__aarch64__) + #elif JUCE_ARM #include "native/juce_neon_SIMDNativeOps.h" #else #error "SIMD register support not implemented for this platform"