aboutsummaryrefslogtreecommitdiff
path: root/core/simd
diff options
context:
space:
mode:
authorBarinzaya <barinzaya@gmail.com>2025-05-06 01:29:08 -0400
committerBarinzaya <barinzaya@gmail.com>2025-05-06 01:44:10 -0400
commit41bf1ab6dd13a08aea50fb4f6600d66bd4a237bb (patch)
tree4020253649eca9fa00a808d41d1c737a07d85df4 /core/simd
parent2224911aca77d15cfdb5ae19e16e9c88ed6edea9 (diff)
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.
Diffstat (limited to 'core/simd')
-rw-r--r--core/simd/x86/bmi.odin79
-rw-r--r--core/simd/x86/bmi2.odin46
2 files changed, 125 insertions, 0 deletions
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 ---
+}