// All of the architecture-specific extensions we care to look for. // Note: Checking for impossible extensions will always turn into a no-op (ex. NEON support on x64). ISA_Extension :: enum { // x64 sse2; sse3; sse41; sse42; ssse3; avx; avx2; avx512cd; avx512f; avx512vnni; // arm64 neon; // riscv rv64ip; } // Returns true if the extension is supported by the current architecture. arch_supports :: inline ($ext: ISA_Extension) -> bool { lazy_init_cpu_info(); return arch_has_extension(ext); } // Returns true if any of the extensions are supported by the current architecture. arch_supports_any :: inline ($extensions: ..ISA_Extension) -> bool { lazy_init_cpu_info(); res: bool; #insert -> string { b: basic.String_Builder; for extensions { basic.print_to_builder(*b, "res ||= arch_has_extension(.%);\n", it); } return basic.builder_to_string(*b); } return res; } // Returns true if all of the extensions are supported by the current architecture. arch_supports_all :: inline ($extensions: ..ISA_Extension) -> bool { lazy_init_cpu_info(); res: bool; #insert -> string { b: basic.String_Builder; for extensions { basic.print_to_builder(*b, "res &&= arch_has_extension(.%);\n", it); } return basic.builder_to_string(*b); } return res; } #scope_file; // @note(judah): this assumes lazy_init_cpu_info was already called arch_has_extension :: inline ($ext: ISA_Extension) -> bool { #if CPU == { case .X64; #if ext == { case .sse2; return x64.check_feature(info.feature_leaves, .SSE2); case .sse3; return x64.check_feature(info.feature_leaves, .SSE3); case .sse41; return x64.check_feature(info.feature_leaves, .SSE4_1); case .sse42; return x64.check_feature(info.feature_leaves, .SSE4_2); case .ssse3; return x64.check_feature(info.feature_leaves, .SSSE3); case .avx; return x64.check_feature(info.feature_leaves, .AVX); case .avx2; return x64.check_feature(info.feature_leaves, .AVX2); case .avx512cd; return x64.check_feature(info.feature_leaves, .AVX512CD); case .avx512f; return x64.check_feature(info.feature_leaves, .AVX512F); case .avx512vnni; return x64.check_feature(info.feature_leaves, .AVX512_VNNI); } case .ARM64; #if ext == { case .neon; return true; // @note(judah): it's safe to assume neon support if we're on arm (for now) } } return false; } info_initialized := false; lazy_init_cpu_info :: () #expand { if info_initialized return; info_initialized = true; #if CPU == .X64 { info = x64.get_cpu_info(); } } #if CPU == { case .X64; info: x64.Cpu_X86; x64 :: #import "Machine_X64"; // @future } basic :: #import "Basic"; // @future