From 41bf1ab6dd13a08aea50fb4f6600d66bd4a237bb Mon Sep 17 00:00:00 2001 From: Barinzaya Date: Tue, 6 May 2025 01:29:08 -0400 Subject: [PATCH] Added BMI and BMI2 intrinsics. The BMI ones mostly aren't particularly interesting--they're mostly trivially representable in-language--but PDEP and PEXT from BMI2 could be. --- core/simd/x86/bmi.odin | 79 +++++++++++++++++++++++++++++++++++++++++ core/simd/x86/bmi2.odin | 46 ++++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100644 core/simd/x86/bmi.odin create mode 100644 core/simd/x86/bmi2.odin diff --git a/core/simd/x86/bmi.odin b/core/simd/x86/bmi.odin new file mode 100644 index 000000000..661272dbf --- /dev/null +++ b/core/simd/x86/bmi.odin @@ -0,0 +1,79 @@ +#+build i386, amd64 +package simd_x86 + +import "base:intrinsics" + +@(require_results, enable_target_feature="bmi") +_andn_u32 :: #force_inline proc "c" (a, b: u32) -> u32 { + return a &~ b +} +@(require_results, enable_target_feature="bmi") +_andn_u64 :: #force_inline proc "c" (a, b: u64) -> u64 { + return a &~ b +} + +@(require_results, enable_target_feature="bmi") +_bextr_u32 :: #force_inline proc "c" (a, start, len: u32) -> u32 { + return bextr_u32(a, (start & 0xff) | (len << 8)) +} +@(require_results, enable_target_feature="bmi") +_bextr_u64 :: #force_inline proc "c" (a: u64, start, len: u32) -> u64 { + return bextr_u64(a, cast(u64)((start & 0xff) | (len << 8))) +} + +@(require_results, enable_target_feature="bmi") +_bextr2_u32 :: #force_inline proc "c" (a, control: u32) -> u32 { + return bextr_u32(a, control) +} +@(require_results, enable_target_feature="bmi") +_bextr2_u64 :: #force_inline proc "c" (a, control: u64) -> u64 { + return bextr_u64(a, control) +} + +@(require_results, enable_target_feature="bmi") +_blsi_u32 :: #force_inline proc "c" (a: u32) -> u32 { + return a & -a +} +@(require_results, enable_target_feature="bmi") +_blsi_u64 :: #force_inline proc "c" (a: u64) -> u64 { + return a & -a +} + +@(require_results, enable_target_feature="bmi") +_blsmsk_u32 :: #force_inline proc "c" (a: u32) -> u32 { + return a ~ (a-1) +} +@(require_results, enable_target_feature="bmi") +_blsmsk_u64 :: #force_inline proc "c" (a: u64) -> u64 { + return a ~ (a-1) +} + +@(require_results, enable_target_feature="bmi") +_blsr_u32 :: #force_inline proc "c" (a: u32) -> u32 { + return a & (a-1) +} +@(require_results, enable_target_feature="bmi") +_blsr_u64 :: #force_inline proc "c" (a: u64) -> u64 { + return a & (a-1) +} + +@(require_results, enable_target_feature = "bmi") +_tzcnt_u16 :: #force_inline proc "c" (a: u16) -> u16 { + return intrinsics.count_trailing_zeros(a) +} +@(require_results, enable_target_feature = "bmi") +_tzcnt_u32 :: #force_inline proc "c" (a: u32) -> u32 { + return intrinsics.count_trailing_zeros(a) +} +@(require_results, enable_target_feature = "bmi") +_tzcnt_u64 :: #force_inline proc "c" (a: u64) -> u64 { + return intrinsics.count_trailing_zeros(a) +} + +@(private, default_calling_convention = "none") +foreign _ { + @(link_name = "llvm.x86.bmi.bextr.32") + bextr_u32 :: proc(a, control: u32) -> u32 --- + @(link_name = "llvm.x86.bmi.bextr.64") + bextr_u64 :: proc(a, control: u64) -> u64 --- +} diff --git a/core/simd/x86/bmi2.odin b/core/simd/x86/bmi2.odin new file mode 100644 index 000000000..65ce7f77c --- /dev/null +++ b/core/simd/x86/bmi2.odin @@ -0,0 +1,46 @@ +#+build i386, amd64 +package simd_x86 + +@(require_results, enable_target_feature = "bmi2") +_bzhi_u32 :: #force_inline proc "c" (a, index: u32) -> u32 { + return bzhi_u32(a, index) +} +@(require_results, enable_target_feature = "bmi2") +_bzhi_u64 :: #force_inline proc "c" (a, index: u64) -> u64 { + return bzhi_u64(a, index) +} + +@(require_results, enable_target_feature = "bmi2") +_pdep_u32 :: #force_inline proc "c" (a, mask: u32) -> u32 { + return pdep_u32(a, mask) +} +@(require_results, enable_target_feature = "bmi2") +_pdep_u64 :: #force_inline proc "c" (a, mask: u64) -> u64 { + return pdep_u64(a, mask) +} + +@(require_results, enable_target_feature = "bmi2") +_pext_u32 :: #force_inline proc "c" (a, mask: u32) -> u32 { + return pext_u32(a, mask) +} +@(require_results, enable_target_feature = "bmi2") +_pext_u64 :: #force_inline proc "c" (a, mask: u64) -> u64 { + return pext_u64(a, mask) +} + + +@(private, default_calling_convention = "none") +foreign _ { + @(link_name = "llvm.x86.bmi.bzhi.32") + bzhi_u32 :: proc(a, index: u32) -> u32 --- + @(link_name = "llvm.x86.bmi.bzhi.64") + bzhi_u64 :: proc(a, index: u64) -> u64 --- + @(link_name = "llvm.x86.bmi.pdep.32") + pdep_u32 :: proc(a, mask: u32) -> u32 --- + @(link_name = "llvm.x86.bmi.pdep.64") + pdep_u64 :: proc(a, mask: u64) -> u64 --- + @(link_name = "llvm.x86.bmi.pext.32") + pext_u32 :: proc(a, mask: u32) -> u32 --- + @(link_name = "llvm.x86.bmi.pext.64") + pext_u64 :: proc(a, mask: u64) -> u64 --- +}