Merge pull request #1807 from odin-lang/simd-dev

Generic #simd type and intrinsics
This commit is contained in:
gingerBill
2022-05-31 11:52:24 +01:00
committed by GitHub
43 changed files with 5446 additions and 378 deletions
+91 -8
View File
@@ -6,12 +6,14 @@ package intrinsics
is_package_imported :: proc(package_name: string) -> bool ---
// Types
simd_vector :: proc($N: int, $T: typeid) -> type/#simd[N]T
soa_struct :: proc($N: int, $T: typeid) -> type/#soa[N]T
// Volatile
volatile_load :: proc(dst: ^$T) -> T ---
volatile_store :: proc(dst: ^$T, val: T) -> T ---
volatile_store :: proc(dst: ^$T, val: T) ---
non_temporal_load :: proc(dst: ^$T) -> T ---
non_temporal_store :: proc(dst: ^$T, val: T) ---
// Trapping
debug_trap :: proc() ---
@@ -23,18 +25,20 @@ alloca :: proc(size, align: int) -> [^]u8 ---
cpu_relax :: proc() ---
read_cycle_counter :: proc() -> i64 ---
count_ones :: proc(x: $T) -> T where type_is_integer(T) ---
count_zeros :: proc(x: $T) -> T where type_is_integer(T) ---
count_trailing_zeros :: proc(x: $T) -> T where type_is_integer(T) ---
count_leading_zeros :: proc(x: $T) -> T where type_is_integer(T) ---
reverse_bits :: proc(x: $T) -> T where type_is_integer(T) ---
count_ones :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
count_zeros :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
count_trailing_zeros :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
count_leading_zeros :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
reverse_bits :: proc(x: $T) -> T where type_is_integer(T) || type_is_simd_vector(T) ---
byte_swap :: proc(x: $T) -> T where type_is_integer(T) || type_is_float(T) ---
overflow_add :: proc(lhs, rhs: $T) -> (T, bool) #optional_ok ---
overflow_sub :: proc(lhs, rhs: $T) -> (T, bool) #optional_ok ---
overflow_mul :: proc(lhs, rhs: $T) -> (T, bool) #optional_ok ---
sqrt :: proc(x: $T) -> T where type_is_float(T) ---
sqrt :: proc(x: $T) -> T where type_is_float(T) || (type_is_simd_vector(T) && type_is_float(type_elem_type(T))) ---
fused_mul_add :: proc(a, b, c: $T) -> T where type_is_float(T) || (type_is_simd_vector(T) && type_is_float(type_elem_type(T))) ---
mem_copy :: proc(dst, src: rawptr, len: int) ---
mem_copy_non_overlapping :: proc(dst, src: rawptr, len: int) ---
@@ -186,6 +190,81 @@ type_hasher_proc :: proc($T: typeid) -> (hasher: proc "contextless" (data: rawpt
constant_utf16_cstring :: proc($literal: string) -> [^]u16 ---
// SIMD related
simd_add :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_sub :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_mul :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_div :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_rem :: proc(a, b: #simd[N]T) -> #simd[N]T ---
// Keeps Odin's Behaviour
// (x << y) if y <= mask else 0
simd_shl :: proc(a: #simd[N]T, b: #simd[N]Unsigned_Integer) -> #simd[N]T ---
simd_shr :: proc(a: #simd[N]T, b: #simd[N]Unsigned_Integer) -> #simd[N]T ---
// Similar to C's Behaviour
// x << (y & mask)
simd_shl_masked :: proc(a: #simd[N]T, b: #simd[N]Unsigned_Integer) -> #simd[N]T ---
simd_shr_masked :: proc(a: #simd[N]T, b: #simd[N]Unsigned_Integer) -> #simd[N]T ---
simd_add_sat :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_sub_sat :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_and :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_or :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_xor :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_and_not :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_neg :: proc(a: #simd[N]T) -> #simd[N]T ---
simd_abs :: proc(a: #simd[N]T) -> #simd[N]T ---
simd_min :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_max :: proc(a, b: #simd[N]T) -> #simd[N]T ---
simd_clamp :: proc(v, min, max: #simd[N]T) -> #simd[N]T ---
// Return an unsigned integer of the same size as the input type
// NOT A BOOLEAN
// element-wise:
// false => 0x00...00
// true => 0xff...ff
simd_lanes_eq :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
simd_lanes_ne :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
simd_lanes_lt :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
simd_lanes_le :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
simd_lanes_gt :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
simd_lanes_ge :: proc(a, b: #simd[N]T) -> #simd[N]Integer ---
simd_extract :: proc(a: #simd[N]T, idx: uint) -> T ---
simd_replace :: proc(a: #simd[N]T, idx: uint, elem: T) -> #simd[N]T ---
simd_reduce_add_ordered :: proc(a: #simd[N]T) -> T ---
simd_reduce_mul_ordered :: proc(a: #simd[N]T) -> T ---
simd_reduce_min :: proc(a: #simd[N]T) -> T ---
simd_reduce_max :: proc(a: #simd[N]T) -> T ---
simd_reduce_and :: proc(a: #simd[N]T) -> T ---
simd_reduce_or :: proc(a: #simd[N]T) -> T ---
simd_reduce_xor :: proc(a: #simd[N]T) -> T ---
simd_shuffle :: proc(a, b: #simd[N]T, indices: ..int) -> #simd[len(indices)]T ---
simd_select :: proc(cond: #simd[N]boolean_or_integer, true, false: #simd[N]T) -> #simd[N]T ---
// Lane-wise operations
simd_ceil :: proc(a: #simd[N]any_float) -> #simd[N]any_float ---
simd_floor :: proc(a: #simd[N]any_float) -> #simd[N]any_float ---
simd_trunc :: proc(a: #simd[N]any_float) -> #simd[N]any_float ---
// rounding to the nearest integral value; if two values are equally near, rounds to the even one
simd_nearest :: proc(a: #simd[N]any_float) -> #simd[N]any_float ---
simd_to_bits :: proc(v: #simd[N]T) -> #simd[N]Integer where size_of(T) == size_of(Integer), type_is_unsigned(Integer) ---
// equivalent a swizzle with descending indices, e.g. reserve(a, 3, 2, 1, 0)
simd_reverse :: proc(a: #simd[N]T) -> #simd[N]T ---
simd_rotate_left :: proc(a: #simd[N]T, $offset: int) -> #simd[N]T ---
simd_rotate_right :: proc(a: #simd[N]T, $offset: int) -> #simd[N]T ---
// WASM targets only
wasm_memory_grow :: proc(index, delta: uintptr) -> int ---
wasm_memory_size :: proc(index: uintptr) -> int ---
@@ -199,6 +278,10 @@ wasm_memory_size :: proc(index: uintptr) -> int ---
wasm_memory_atomic_wait32 :: proc(ptr: ^u32, expected: u32, timeout_ns: i64) -> u32 ---
wasm_memory_atomic_notify32 :: proc(ptr: ^u32, waiters: u32) -> (waiters_woken_up: u32) ---
// x86 Targets (i386, amd64)
x86_cpuid :: proc(ax, cx: u32) -> (eax, ebc, ecx, edx: u32) ---
x86_xgetbv :: proc(cx: u32) -> (eax, edx: u32) ---
// Darwin targets only
objc_object :: struct{}
+1
View File
@@ -21,6 +21,7 @@ make_any :: proc "contextless" (data: rawptr, id: typeid) -> any {
}
raw_array_data :: runtime.raw_array_data
raw_simd_data :: runtime.raw_simd_data
raw_string_data :: runtime.raw_string_data
raw_slice_data :: runtime.raw_slice_data
raw_dynamic_array_data :: runtime.raw_dynamic_array_data
+5 -1
View File
@@ -604,6 +604,10 @@ raw_array_data :: proc "contextless" (a: $P/^($T/[$N]$E)) -> [^]E {
return ([^]E)(a)
}
@builtin
raw_simd_data :: proc "contextless" (a: $P/^($T/#simd[$N]$E)) -> [^]E {
return ([^]E)(a)
}
@builtin
raw_slice_data :: proc "contextless" (s: $S/[]$E) -> [^]E {
ptr := (transmute(Raw_Slice)s).data
return ([^]E)(ptr)
@@ -619,7 +623,7 @@ raw_string_data :: proc "contextless" (s: $S/string) -> [^]u8 {
}
@builtin
raw_data :: proc{raw_array_data, raw_slice_data, raw_dynamic_array_data, raw_string_data}
raw_data :: proc{raw_array_data, raw_slice_data, raw_dynamic_array_data, raw_string_data, raw_simd_data}
+188
View File
@@ -0,0 +1,188 @@
package simd
import "core:builtin"
import "core:intrinsics"
// 128-bit vector aliases
u8x16 :: #simd[16]u8
i8x16 :: #simd[16]i8
u16x8 :: #simd[8]u16
i16x8 :: #simd[8]i16
u32x4 :: #simd[4]u32
i32x4 :: #simd[4]i32
u64x2 :: #simd[2]u64
i64x2 :: #simd[2]i64
f32x4 :: #simd[4]f32
f64x2 :: #simd[2]f64
boolx16 :: #simd[16]bool
b8x16 :: #simd[16]b8
b16x8 :: #simd[8]b16
b32x4 :: #simd[4]b32
b64x2 :: #simd[2]b64
// 256-bit vector aliases
u8x32 :: #simd[32]u8
i8x32 :: #simd[32]i8
u16x16 :: #simd[16]u16
i16x16 :: #simd[16]i16
u32x8 :: #simd[8]u32
i32x8 :: #simd[8]i32
u64x4 :: #simd[4]u64
i64x4 :: #simd[4]i64
f32x8 :: #simd[8]f32
f64x4 :: #simd[4]f64
boolx32 :: #simd[32]bool
b8x32 :: #simd[32]b8
b16x16 :: #simd[16]b16
b32x8 :: #simd[8]b32
b64x4 :: #simd[4]b64
// 512-bit vector aliases
u8x64 :: #simd[64]u8
i8x64 :: #simd[64]i8
u16x32 :: #simd[32]u16
i16x32 :: #simd[32]i16
u32x16 :: #simd[16]u32
i32x16 :: #simd[16]i32
u64x8 :: #simd[8]u64
i64x8 :: #simd[8]i64
f32x16 :: #simd[16]f32
f64x8 :: #simd[8]f64
boolx64 :: #simd[64]bool
b8x64 :: #simd[64]b8
b16x32 :: #simd[32]b16
b32x16 :: #simd[16]b32
b64x8 :: #simd[8]b64
add :: intrinsics.simd_add
sub :: intrinsics.simd_sub
mul :: intrinsics.simd_mul
div :: intrinsics.simd_div
rem :: intrinsics.simd_rem // integers only
// Keeps Odin's Behaviour
// (x << y) if y <= mask else 0
shl :: intrinsics.simd_shl
shr :: intrinsics.simd_shr
// Similar to C's Behaviour
// x << (y & mask)
shl_masked :: intrinsics.simd_shl_masked
shr_masked :: intrinsics.simd_shr_masked
// Saturation Arithmetic
add_sat :: intrinsics.simd_add_sat
sub_sat :: intrinsics.simd_sub_sat
and :: intrinsics.simd_and
or :: intrinsics.simd_or
xor :: intrinsics.simd_xor
and_not :: intrinsics.simd_and_not
neg :: intrinsics.simd_neg
abs :: intrinsics.simd_abs
min :: intrinsics.simd_min
max :: intrinsics.simd_max
clamp :: intrinsics.simd_clamp
// Return an unsigned integer of the same size as the input type
// NOT A BOOLEAN
// element-wise:
// false => 0x00...00
// true => 0xff...ff
lanes_eq :: intrinsics.simd_lanes_eq
lanes_ne :: intrinsics.simd_lanes_ne
lanes_lt :: intrinsics.simd_lanes_lt
lanes_le :: intrinsics.simd_lanes_le
lanes_gt :: intrinsics.simd_lanes_gt
lanes_ge :: intrinsics.simd_lanes_ge
// extract :: proc(a: #simd[N]T, idx: uint) -> T
extract :: intrinsics.simd_extract
// replace :: proc(a: #simd[N]T, idx: uint, elem: T) -> #simd[N]T
replace :: intrinsics.simd_replace
reduce_add_ordered :: intrinsics.simd_reduce_add_ordered
reduce_mul_ordered :: intrinsics.simd_reduce_mul_ordered
reduce_min :: intrinsics.simd_reduce_min
reduce_max :: intrinsics.simd_reduce_max
reduce_and :: intrinsics.simd_reduce_and
reduce_or :: intrinsics.simd_reduce_or
reduce_xor :: intrinsics.simd_reduce_xor
// swizzle :: proc(a: #simd[N]T, indices: ..int) -> #simd[len(indices)]T
swizzle :: builtin.swizzle
// shuffle :: proc(a, b: #simd[N]T, indices: #simd[max 2*N]u32) -> #simd[len(indices)]T
shuffle :: intrinsics.simd_shuffle
// select :: proc(cond: #simd[N]boolean_or_integer, true, false: #simd[N]T) -> #simd[N]T
select :: intrinsics.simd_select
sqrt :: intrinsics.sqrt
ceil :: intrinsics.simd_ceil
floor :: intrinsics.simd_floor
trunc :: intrinsics.simd_trunc
nearest :: intrinsics.simd_nearest
to_bits :: intrinsics.simd_to_bits
lanes_reverse :: intrinsics.simd_lanes_reverse
lanes_rotate_left :: intrinsics.simd_lanes_rotate_left
lanes_rotate_right :: intrinsics.simd_lanes_rotate_right
count_ones :: intrinsics.count_ones
count_zeros :: intrinsics.count_zeros
count_trailing_zeros :: intrinsics.count_trailing_zeros
count_leading_zeros :: intrinsics.count_leading_zeros
reverse_bits :: intrinsics.reverse_bits
fused_mul_add :: intrinsics.fused_mul_add
fma :: intrinsics.fused_mul_add
to_array_ptr :: #force_inline proc "contextless" (v: ^#simd[$LANES]$E) -> ^[LANES]E {
return (^[LANES]E)(v)
}
to_array :: #force_inline proc "contextless" (v: #simd[$LANES]$E) -> [LANES]E {
return transmute([LANES]E)(v)
}
from_array :: #force_inline proc "contextless" (v: $A/[$LANES]$E) -> #simd[LANES]E {
return transmute(#simd[LANES]E)v
}
from_slice :: proc($T: typeid/#simd[$LANES]$E, slice: []E) -> T {
assert(len(slice) >= LANES, "slice length must be a least the number of lanes")
array: [LANES]E
#no_bounds_check for i in 0..<LANES {
array[i] = slice[i]
}
return transmute(T)array
}
bit_not :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_integer(E) {
return xor(v, T(~E(0)))
}
copysign :: #force_inline proc "contextless" (v, sign: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_float(E) {
neg_zero := to_bits(T(-0.0))
sign_bit := to_bits(sign) & neg_zero
magnitude := to_bits(v) &~ neg_zero
return transmute(T)(sign_bit|magnitude)
}
signum :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_float(E) {
is_nan := lanes_ne(v, v)
return select(is_nan, v, copysign(T(1), v))
}
recip :: #force_inline proc "contextless" (v: $T/#simd[$LANES]$E) -> T where intrinsics.type_is_float(E) {
return T(1) / v
}
+24
View File
@@ -0,0 +1,24 @@
//+build i386, amd64
package simd_x86
import "core:intrinsics"
@(require_results, enable_target_feature="lzcnt")
_lzcnt_u32 :: #force_inline proc "c" (x: u32) -> u32 {
return intrinsics.count_leading_zeros(x)
}
@(require_results, enable_target_feature="popcnt")
_popcnt32 :: #force_inline proc "c" (x: u32) -> i32 {
return i32(intrinsics.count_ones(x))
}
when ODIN_ARCH == .amd64 {
@(require_results, enable_target_feature="lzcnt")
_lzcnt_u64 :: #force_inline proc "c" (x: u64) -> u64 {
return intrinsics.count_leading_zeros(x)
}
@(require_results, enable_target_feature="popcnt")
_popcnt64 :: #force_inline proc "c" (x: u64) -> i32 {
return i32(intrinsics.count_ones(x))
}
}
+56
View File
@@ -0,0 +1,56 @@
//+build i386, amd64
package simd_x86
@(require_results)
_addcarry_u32 :: #force_inline proc "c" (c_in: u8, a: u32, b: u32, out: ^u32) -> u8 {
x, y := llvm_addcarry_u32(c_in, a, b)
out^ = y
return x
}
@(require_results)
_addcarryx_u32 :: #force_inline proc "c" (c_in: u8, a: u32, b: u32, out: ^u32) -> u8 {
return llvm_addcarryx_u32(c_in, a, b, out)
}
@(require_results)
_subborrow_u32 :: #force_inline proc "c" (c_in: u8, a: u32, b: u32, out: ^u32) -> u8 {
x, y := llvm_subborrow_u32(c_in, a, b)
out^ = y
return x
}
when ODIN_ARCH == .amd64 {
@(require_results)
_addcarry_u64 :: #force_inline proc "c" (c_in: u8, a: u64, b: u64, out: ^u64) -> u8 {
x, y := llvm_addcarry_u64(c_in, a, b)
out^ = y
return x
}
@(require_results)
_addcarryx_u64 :: #force_inline proc "c" (c_in: u8, a: u64, b: u64, out: ^u64) -> u8 {
return llvm_addcarryx_u64(c_in, a, b, out)
}
@(require_results)
_subborrow_u64 :: #force_inline proc "c" (c_in: u8, a: u64, b: u64, out: ^u64) -> u8 {
x, y := llvm_subborrow_u64(c_in, a, b)
out^ = y
return x
}
}
@(private, default_calling_convention="c")
foreign _ {
@(link_name="llvm.x86.addcarry.32")
llvm_addcarry_u32 :: proc(a: u8, b: u32, c: u32) -> (u8, u32) ---
@(link_name="llvm.x86.addcarryx.u32")
llvm_addcarryx_u32 :: proc(a: u8, b: u32, c: u32, d: rawptr) -> u8 ---
@(link_name="llvm.x86.subborrow.32")
llvm_subborrow_u32 :: proc(a: u8, b: u32, c: u32) -> (u8, u32) ---
// amd64 only
@(link_name="llvm.x86.addcarry.64")
llvm_addcarry_u64 :: proc(a: u8, b: u64, c: u64) -> (u8, u64) ---
@(link_name="llvm.x86.addcarryx.u64")
llvm_addcarryx_u64 :: proc(a: u8, b: u64, c: u64, d: rawptr) -> u8 ---
@(link_name="llvm.x86.subborrow.64")
llvm_subborrow_u64 :: proc(a: u8, b: u64, c: u64) -> (u8, u64) ---
}
+8
View File
@@ -0,0 +1,8 @@
//+build amd64
package simd_x86
import "core:intrinsics"
cmpxchg16b :: #force_inline proc "c" (dst: ^u128, old, new: u128, $success, $failure: intrinsics.Atomic_Memory_Order) -> (val: u128) {
return intrinsics.atomic_compare_exchange_strong_explicit(dst, old, new, success, failure)
}
+94
View File
@@ -0,0 +1,94 @@
//+build i386, amd64
package simd_x86
import "core:intrinsics"
// cpuid :: proc(ax, cx: u32) -> (eax, ebc, ecx, edx: u32) ---
cpuid :: intrinsics.x86_cpuid
// xgetbv :: proc(cx: u32) -> (eax, edx: u32) ---
xgetbv :: intrinsics.x86_xgetbv
CPU_Feature :: enum u64 {
aes, // AES hardware implementation (AES NI)
adx, // Multi-precision add-carry instruction extensions
avx, // Advanced vector extension
avx2, // Advanced vector extension 2
bmi1, // Bit manipulation instruction set 1
bmi2, // Bit manipulation instruction set 2
erms, // Enhanced REP for MOVSB and STOSB
fma, // Fused-multiply-add instructions
os_xsave, // OS supports XSAVE/XRESTOR for saving/restoring XMM registers.
pclmulqdq, // PCLMULQDQ instruction - most often used for AES-GCM
popcnt, // Hamming weight instruction POPCNT.
rdrand, // RDRAND instruction (on-chip random number generator)
rdseed, // RDSEED instruction (on-chip random number generator)
sse2, // Streaming SIMD extension 2 (always available on amd64)
sse3, // Streaming SIMD extension 3
ssse3, // Supplemental streaming SIMD extension 3
sse41, // Streaming SIMD extension 4 and 4.1
sse42, // Streaming SIMD extension 4 and 4.2
}
CPU_Features :: distinct bit_set[CPU_Feature; u64]
cpu_features: Maybe(CPU_Features)
@(init, private)
init_cpu_features :: proc "c" () {
is_set :: #force_inline proc "c" (hwc: u32, value: u32) -> bool {
return hwc&value != 0
}
try_set :: #force_inline proc "c" (set: ^CPU_Features, feature: CPU_Feature, hwc: u32, value: u32) {
if is_set(hwc, value) {
set^ += {feature}
}
}
max_id, _, _, _ := cpuid(0, 0)
if max_id < 1 {
return
}
set: CPU_Features
_, _, ecx1, edx1 := cpuid(1, 0)
try_set(&set, .sse2, 26, edx1)
try_set(&set, .sse3, 0, ecx1)
try_set(&set, .pclmulqdq, 1, ecx1)
try_set(&set, .ssse3, 9, ecx1)
try_set(&set, .fma, 12, ecx1)
try_set(&set, .sse41, 19, ecx1)
try_set(&set, .sse42, 20, ecx1)
try_set(&set, .popcnt, 23, ecx1)
try_set(&set, .aes, 25, ecx1)
try_set(&set, .os_xsave, 27, ecx1)
try_set(&set, .rdrand, 30, ecx1)
os_supports_avx := false
if .os_xsave in set {
eax, _ := xgetbv(0)
os_supports_avx = is_set(1, eax) && is_set(2, eax)
}
if os_supports_avx {
try_set(&set, .avx, 28, ecx1)
}
if max_id < 7 {
return
}
_, ebx7, _, _ := cpuid(7, 0)
try_set(&set, .bmi1, 3, ebx7)
if os_supports_avx {
try_set(&set, .avx2, 5, ebx7)
}
try_set(&set, .bmi2, 8, ebx7)
try_set(&set, .erms, 9, ebx7)
try_set(&set, .rdseed, 18, ebx7)
try_set(&set, .adx, 19, ebx7)
cpu_features = set
}
+36
View File
@@ -0,0 +1,36 @@
//+build i386, amd64
package simd_x86
@(enable_target_feature="fxsr")
_fxsave :: #force_inline proc "c" (mem_addr: rawptr) {
fxsave(mem_addr)
}
@(enable_target_feature="fxsr")
_fxrstor :: #force_inline proc "c" (mem_addr: rawptr) {
fxrstor(mem_addr)
}
when ODIN_ARCH == .amd64 {
@(enable_target_feature="fxsr")
_fxsave64 :: #force_inline proc "c" (mem_addr: rawptr) {
fxsave64(mem_addr)
}
@(enable_target_feature="fxsr")
_fxrstor64 :: #force_inline proc "c" (mem_addr: rawptr) {
fxrstor64(mem_addr)
}
}
@(private, default_calling_convention="c")
foreign _ {
@(link_name="llvm.x86.fxsave")
fxsave :: proc(p: rawptr) ---
@(link_name="llvm.x86.fxrstor")
fxrstor :: proc(p: rawptr) ---
// amd64 only
@(link_name="llvm.x86.fxsave64")
fxsave64 :: proc(p: rawptr) ---
@(link_name="llvm.x86.fxrstor64")
fxrstor64 :: proc(p: rawptr) ---
}
+13
View File
@@ -0,0 +1,13 @@
//+build i386, amd64
package simd_x86
@(require_results, enable_target_feature="pclmulqdq")
_mm_clmulepi64_si128 :: #force_inline proc "c" (a, b: __m128i, $IMM8: u8) -> __m128i {
return pclmulqdq(a, b, u8(IMM8))
}
@(private, default_calling_convention="c")
foreign _ {
@(link_name="llvm.x86.pclmulqdq")
pclmulqdq :: proc(a, round_key: __m128i, #const imm8: u8) -> __m128i ---
}
+20
View File
@@ -0,0 +1,20 @@
//+build i386, amd64
package simd_x86
@(require_results)
_rdtsc :: #force_inline proc "c" () -> u64 {
return rdtsc()
}
@(require_results)
__rdtscp :: #force_inline proc "c" (aux: ^u32) -> u64 {
return rdtscp(aux)
}
@(private, default_calling_convention="c")
foreign _ {
@(link_name="llvm.x86.rdtsc")
rdtsc :: proc() -> u64 ---
@(link_name="llvm.x86.rdtscp")
rdtscp :: proc(aux: rawptr) -> u64 ---
}
+49
View File
@@ -0,0 +1,49 @@
//+build i386, amd64
package simd_x86
@(require_results, enable_target_feature="sha")
_mm_sha1msg1_epu32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)sha1msg1(transmute(i32x4)a, transmute(i32x4)b)
}
@(require_results, enable_target_feature="sha")
_mm_sha1msg2_epu32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)sha1msg2(transmute(i32x4)a, transmute(i32x4)b)
}
@(require_results, enable_target_feature="sha")
_mm_sha1nexte_epu32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)sha1nexte(transmute(i32x4)a, transmute(i32x4)b)
}
@(require_results, enable_target_feature="sha")
_mm_sha1rnds4_epu32 :: #force_inline proc "c" (a, b: __m128i, $FUNC: u32) -> __m128i where 0 <= FUNC, FUNC <= 3 {
return transmute(__m128i)sha1rnds4(transmute(i32x4)a, transmute(i32x4)b, u8(FUNC & 0xff))
}
@(require_results, enable_target_feature="sha")
_mm_sha256msg1_epu32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)sha256msg1(transmute(i32x4)a, transmute(i32x4)b)
}
@(require_results, enable_target_feature="sha")
_mm_sha256msg2_epu32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)sha256msg2(transmute(i32x4)a, transmute(i32x4)b)
}
@(require_results, enable_target_feature="sha")
_mm_sha256rnds2_epu32 :: #force_inline proc "c" (a, b, k: __m128i) -> __m128i {
return transmute(__m128i)sha256rnds2(transmute(i32x4)a, transmute(i32x4)b, transmute(i32x4)k)
}
@(private, default_calling_convention="c")
foreign _ {
@(link_name="llvm.x86.sha1msg1")
sha1msg1 :: proc(a, b: i32x4) -> i32x4 ---
@(link_name="llvm.x86.sha1msg2")
sha1msg2 :: proc(a, b: i32x4) -> i32x4 ---
@(link_name="llvm.x86.sha1nexte")
sha1nexte :: proc(a, b: i32x4) -> i32x4 ---
@(link_name="llvm.x86.sha1rnds4")
sha1rnds4 :: proc(a, b: i32x4, #const c: u8) -> i32x4 ---
@(link_name="llvm.x86.sha256msg1")
sha256msg1 :: proc(a, b: i32x4) -> i32x4 ---
@(link_name="llvm.x86.sha256msg2")
sha256msg2 :: proc(a, b: i32x4) -> i32x4 ---
@(link_name="llvm.x86.sha256rnds2")
sha256rnds2 :: proc(a, b, k: i32x4) -> i32x4 ---
}
+618
View File
@@ -0,0 +1,618 @@
//+build i386, amd64
package simd_x86
import "core:intrinsics"
import "core:simd"
// _MM_SHUFFLE(z, y, x, w) -> (z<<6 | y<<4 | x<<2 | w)
_MM_SHUFFLE :: intrinsics.simd_x86__MM_SHUFFLE
_MM_HINT_T0 :: 3
_MM_HINT_T1 :: 2
_MM_HINT_T2 :: 1
_MM_HINT_NTA :: 0
_MM_HINT_ET0 :: 7
_MM_HINT_ET1 :: 6
_MM_EXCEPT_INVALID :: 0x0001
_MM_EXCEPT_DENORM :: 0x0002
_MM_EXCEPT_DIV_ZERO :: 0x0004
_MM_EXCEPT_OVERFLOW :: 0x0008
_MM_EXCEPT_UNDERFLOW :: 0x0010
_MM_EXCEPT_INEXACT :: 0x0020
_MM_EXCEPT_MASK :: 0x003f
_MM_MASK_INVALID :: 0x0080
_MM_MASK_DENORM :: 0x0100
_MM_MASK_DIV_ZERO :: 0x0200
_MM_MASK_OVERFLOW :: 0x0400
_MM_MASK_UNDERFLOW :: 0x0800
_MM_MASK_INEXACT :: 0x1000
_MM_MASK_MASK :: 0x1f80
_MM_ROUND_NEAREST :: 0x0000
_MM_ROUND_DOWN :: 0x2000
_MM_ROUND_UP :: 0x4000
_MM_ROUND_TOWARD_ZERO :: 0x6000
_MM_ROUND_MASK :: 0x6000
_MM_FLUSH_ZERO_MASK :: 0x8000
_MM_FLUSH_ZERO_ON :: 0x8000
_MM_FLUSH_ZERO_OFF :: 0x0000
@(require_results, enable_target_feature="sse")
_mm_add_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return addss(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_add_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return simd.add(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_sub_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return subss(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_sub_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return simd.sub(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_mul_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return mulss(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_mul_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return simd.mul(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_div_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return divss(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_div_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return simd.div(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_sqrt_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return sqrtss(a)
}
@(require_results, enable_target_feature="sse")
_mm_sqrt_ps :: #force_inline proc "c" (a: __m128) -> __m128 {
return sqrtps(a)
}
@(require_results, enable_target_feature="sse")
_mm_rcp_ss :: #force_inline proc "c" (a: __m128) -> __m128 {
return rcpss(a)
}
@(require_results, enable_target_feature="sse")
_mm_rcp_ps :: #force_inline proc "c" (a: __m128) -> __m128 {
return rcpps(a)
}
@(require_results, enable_target_feature="sse")
_mm_rsqrt_ss :: #force_inline proc "c" (a: __m128) -> __m128 {
return rsqrtss(a)
}
@(require_results, enable_target_feature="sse")
_mm_rsqrt_ps :: #force_inline proc "c" (a: __m128) -> __m128 {
return rsqrtps(a)
}
@(require_results, enable_target_feature="sse")
_mm_min_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return minss(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_min_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return minps(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_max_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return maxss(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_max_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return maxps(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_and_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return transmute(__m128)simd.and(transmute(__m128i)a, transmute(__m128i)b)
}
@(require_results, enable_target_feature="sse")
_mm_andnot_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return transmute(__m128)simd.and_not(transmute(__m128i)a, transmute(__m128i)b)
}
@(require_results, enable_target_feature="sse")
_mm_or_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return transmute(__m128)simd.or(transmute(__m128i)a, transmute(__m128i)b)
}
@(require_results, enable_target_feature="sse")
_mm_xor_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return transmute(__m128)simd.xor(transmute(__m128i)a, transmute(__m128i)b)
}
@(require_results, enable_target_feature="sse")
_mm_cmpeq_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return cmpss(a, b, 0)
}
@(require_results, enable_target_feature="sse")
_mm_cmplt_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return cmpss(a, b, 1)
}
@(require_results, enable_target_feature="sse")
_mm_cmple_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return cmpss(a, b, 2)
}
@(require_results, enable_target_feature="sse")
_mm_cmpgt_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return simd.shuffle(a, cmpss(b, a, 1), 4, 1, 2, 3)
}
@(require_results, enable_target_feature="sse")
_mm_cmpge_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return simd.shuffle(a, cmpss(b, a, 2), 4, 1, 2, 3)
}
@(require_results, enable_target_feature="sse")
_mm_cmpneq_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return cmpss(a, b, 4)
}
@(require_results, enable_target_feature="sse")
_mm_cmpnlt_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return cmpss(a, b, 5)
}
@(require_results, enable_target_feature="sse")
_mm_cmpnle_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return cmpss(a, b, 6)
}
@(require_results, enable_target_feature="sse")
_mm_cmpngt_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return simd.shuffle(a, cmpss(b, a, 5), 4, 1, 2, 3)
}
@(require_results, enable_target_feature="sse")
_mm_cmpnge_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return simd.shuffle(a, cmpss(b, a, 6), 4, 1, 2, 3)
}
@(require_results, enable_target_feature="sse")
_mm_cmpord_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return cmpss(a, b, 7)
}
@(require_results, enable_target_feature="sse")
_mm_cmpunord_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return cmpss(a, b, 3)
}
@(require_results, enable_target_feature="sse")
_mm_cmpeq_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return cmpps(a, b, 0)
}
@(require_results, enable_target_feature="sse")
_mm_cmplt_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return cmpps(a, b, 1)
}
@(require_results, enable_target_feature="sse")
_mm_cmple_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return cmpps(a, b, 2)
}
@(require_results, enable_target_feature="sse")
_mm_cmpgt_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return cmpps(b, a, 1)
}
@(require_results, enable_target_feature="sse")
_mm_cmpge_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return cmpps(b, a, 2)
}
@(require_results, enable_target_feature="sse")
_mm_cmpneq_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return cmpps(a, b, 4)
}
@(require_results, enable_target_feature="sse")
_mm_cmpnlt_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return cmpps(a, b, 5)
}
@(require_results, enable_target_feature="sse")
_mm_cmpnle_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return cmpps(a, b, 6)
}
@(require_results, enable_target_feature="sse")
_mm_cmpngt_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return cmpps(b, a, 5)
}
@(require_results, enable_target_feature="sse")
_mm_cmpnge_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return cmpps(b, a, 6)
}
@(require_results, enable_target_feature="sse")
_mm_cmpord_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return cmpps(b, a, 7)
}
@(require_results, enable_target_feature="sse")
_mm_cmpunord_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return cmpps(b, a, 3)
}
@(require_results, enable_target_feature="sse")
_mm_comieq_ss :: #force_inline proc "c" (a, b: __m128) -> b32 {
return comieq_ss(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_comilt_ss :: #force_inline proc "c" (a, b: __m128) -> b32 {
return comilt_ss(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_comile_ss :: #force_inline proc "c" (a, b: __m128) -> b32 {
return comile_ss(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_comigt_ss :: #force_inline proc "c" (a, b: __m128) -> b32 {
return comigt_ss(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_comige_ss :: #force_inline proc "c" (a, b: __m128) -> b32 {
return comige_ss(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_comineq_ss :: #force_inline proc "c" (a, b: __m128) -> b32 {
return comineq_ss(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_ucomieq_ss :: #force_inline proc "c" (a, b: __m128) -> b32 {
return ucomieq_ss(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_ucomilt_ss :: #force_inline proc "c" (a, b: __m128) -> b32 {
return ucomilt_ss(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_ucomile_ss :: #force_inline proc "c" (a, b: __m128) -> b32 {
return ucomile_ss(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_ucomigt_ss :: #force_inline proc "c" (a, b: __m128) -> b32 {
return ucomigt_ss(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_ucomige_ss :: #force_inline proc "c" (a, b: __m128) -> b32 {
return ucomige_ss(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_ucomineq_ss :: #force_inline proc "c" (a, b: __m128) -> b32 {
return ucomineq_ss(a, b)
}
@(require_results, enable_target_feature="sse")
_mm_cvtss_si32 :: #force_inline proc "c" (a: __m128) -> i32 {
return cvtss2si(a)
}
_mm_cvt_ss2si :: _mm_cvtss_si32
_mm_cvttss_si32 :: _mm_cvtss_si32
@(require_results, enable_target_feature="sse")
_mm_cvtss_f32 :: #force_inline proc "c" (a: __m128) -> f32 {
return simd.extract(a, 0)
}
@(require_results, enable_target_feature="sse")
_mm_cvtsi32_ss :: #force_inline proc "c" (a: __m128, b: i32) -> __m128 {
return cvtsi2ss(a, b)
}
_mm_cvt_si2ss :: _mm_cvtsi32_ss
@(require_results, enable_target_feature="sse")
_mm_set_ss :: #force_inline proc "c" (a: f32) -> __m128 {
return __m128{a, 0, 0, 0}
}
@(require_results, enable_target_feature="sse")
_mm_set1_ps :: #force_inline proc "c" (a: f32) -> __m128 {
return __m128(a)
}
_mm_set_ps1 :: _mm_set1_ps
@(require_results, enable_target_feature="sse")
_mm_set_ps :: #force_inline proc "c" (a, b, c, d: f32) -> __m128 {
return __m128{d, c, b, a}
}
@(require_results, enable_target_feature="sse")
_mm_setr_ps :: #force_inline proc "c" (a, b, c, d: f32) -> __m128 {
return __m128{a, b, c, d}
}
@(require_results, enable_target_feature="sse")
_mm_setzero_ps :: #force_inline proc "c" () -> __m128 {
return __m128{0, 0, 0, 0}
}
@(require_results, enable_target_feature="sse")
_mm_shuffle_ps :: #force_inline proc "c" (a, b: __m128, $MASK: u32) -> __m128 {
return simd.shuffle(
a, b,
u32(MASK) & 0b11,
(u32(MASK)>>2) & 0b11,
((u32(MASK)>>4) & 0b11)+4,
((u32(MASK)>>6) & 0b11)+4)
}
@(require_results, enable_target_feature="sse")
_mm_unpackhi_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return simd.shuffle(a, b, 2, 6, 3, 7)
}
@(require_results, enable_target_feature="sse")
_mm_unpacklo_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return simd.shuffle(a, b, 0, 4, 1, 5)
}
@(require_results, enable_target_feature="sse")
_mm_movehl_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return simd.shuffle(a, b, 6, 7, 2, 3)
}
@(require_results, enable_target_feature="sse")
_mm_movelh_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return simd.shuffle(a, b, 0, 1, 4, 5)
}
@(require_results, enable_target_feature="sse")
_mm_movemask_ps :: #force_inline proc "c" (a: __m128) -> u32 {
return movmskps(a)
}
@(require_results, enable_target_feature="sse")
_mm_load_ss :: #force_inline proc "c" (p: ^f32) -> __m128 {
return __m128{p^, 0, 0, 0}
}
@(require_results, enable_target_feature="sse")
_mm_load1_ps :: #force_inline proc "c" (p: ^f32) -> __m128 {
a := p^
return __m128(a)
}
_mm_load_ps1 :: _mm_load1_ps
@(require_results, enable_target_feature="sse")
_mm_load_ps :: #force_inline proc "c" (p: [^]f32) -> __m128 {
return (^__m128)(p)^
}
@(require_results, enable_target_feature="sse")
_mm_loadu_ps :: #force_inline proc "c" (p: [^]f32) -> __m128 {
dst := _mm_undefined_ps()
intrinsics.mem_copy_non_overlapping(&dst, p, size_of(__m128))
return dst
}
@(require_results, enable_target_feature="sse")
_mm_loadr_ps :: #force_inline proc "c" (p: [^]f32) -> __m128 {
return simd.lanes_reverse(_mm_load_ps(p))
}
@(require_results, enable_target_feature="sse")
_mm_loadu_si64 :: #force_inline proc "c" (mem_addr: rawptr) -> __m128i {
a := intrinsics.unaligned_load((^i64)(mem_addr))
return __m128i{a, 0}
}
@(enable_target_feature="sse")
_mm_store_ss :: #force_inline proc "c" (p: ^f32, a: __m128) {
p^ = simd.extract(a, 0)
}
@(enable_target_feature="sse")
_mm_store1_ps :: #force_inline proc "c" (p: [^]f32, a: __m128) {
b := simd.swizzle(a, 0, 0, 0, 0)
(^__m128)(p)^ = b
}
_mm_store_ps1 :: _mm_store1_ps
@(enable_target_feature="sse")
_mm_store_ps :: #force_inline proc "c" (p: [^]f32, a: __m128) {
(^__m128)(p)^ = a
}
@(enable_target_feature="sse")
_mm_storeu_ps :: #force_inline proc "c" (p: [^]f32, a: __m128) {
b := a
intrinsics.mem_copy_non_overlapping(p, &b, size_of(__m128))
}
@(enable_target_feature="sse")
_mm_storer_ps :: #force_inline proc "c" (p: [^]f32, a: __m128) {
(^__m128)(p)^ = simd.lanes_reverse(a)
}
@(require_results, enable_target_feature="sse")
_mm_move_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return simd.shuffle(a, b, 4, 1, 2, 3)
}
@(enable_target_feature="sse")
_mm_sfence :: #force_inline proc "c" () {
sfence()
}
@(require_results, enable_target_feature="sse")
_mm_getcsr :: #force_inline proc "c" () -> (result: u32) {
stmxcsr(&result)
return result
}
@(enable_target_feature="sse")
_mm_setcsr :: #force_inline proc "c" (val: u32) {
val := val
ldmxcsr(&val)
}
@(require_results, enable_target_feature="sse")
_MM_GET_EXCEPTION_MASK :: #force_inline proc "c" () -> u32 {
return _mm_getcsr() & _MM_MASK_MASK
}
@(require_results, enable_target_feature="sse")
_MM_GET_EXCEPTION_STATE :: #force_inline proc "c" () -> u32 {
return _mm_getcsr() & _MM_EXCEPT_MASK
}
@(require_results, enable_target_feature="sse")
_MM_GET_FLUSH_ZERO_MODE :: #force_inline proc "c" () -> u32 {
return _mm_getcsr() & _MM_FLUSH_ZERO_MASK
}
@(require_results, enable_target_feature="sse")
_MM_GET_ROUNDING_MODE :: #force_inline proc "c" () -> u32 {
return _mm_getcsr() & _MM_ROUND_MASK
}
@(enable_target_feature="sse")
_MM_SET_EXCEPTION_MASK :: #force_inline proc "c" (x: u32) {
_mm_setcsr((_mm_getcsr() &~ _MM_MASK_MASK) | x)
}
@(enable_target_feature="sse")
_MM_SET_EXCEPTION_STATE :: #force_inline proc "c" (x: u32) {
_mm_setcsr((_mm_getcsr() &~ _MM_EXCEPT_MASK) | x)
}
@(enable_target_feature="sse")
_MM_SET_FLUSH_ZERO_MODE :: #force_inline proc "c" (x: u32) {
_mm_setcsr((_mm_getcsr() &~ _MM_FLUSH_ZERO_MASK) | x)
}
@(enable_target_feature="sse")
_MM_SET_ROUNDING_MODE :: #force_inline proc "c" (x: u32) {
_mm_setcsr((_mm_getcsr() &~ _MM_ROUND_MASK) | x)
}
@(enable_target_feature="sse")
_mm_prefetch :: #force_inline proc "c" (p: rawptr, $STRATEGY: u32) {
prefetch(p, (STRATEGY>>2)&1, STRATEGY&3, 1)
}
@(require_results, enable_target_feature="sse")
_mm_undefined_ps :: #force_inline proc "c" () -> __m128 {
return _mm_set1_ps(0)
}
@(enable_target_feature="sse")
_MM_TRANSPOSE4_PS :: #force_inline proc "c" (row0, row1, row2, row3: ^__m128) {
tmp0 := _mm_unpacklo_ps(row0^, row1^)
tmp1 := _mm_unpacklo_ps(row2^, row3^)
tmp2 := _mm_unpackhi_ps(row0^, row1^)
tmp3 := _mm_unpackhi_ps(row2^, row3^)
row0^ = _mm_movelh_ps(tmp0, tmp2)
row1^ = _mm_movelh_ps(tmp2, tmp0)
row2^ = _mm_movelh_ps(tmp1, tmp3)
row3^ = _mm_movelh_ps(tmp3, tmp1)
}
@(enable_target_feature="sse")
_mm_stream_ps :: #force_inline proc "c" (addr: [^]f32, a: __m128) {
intrinsics.non_temporal_store((^__m128)(addr), a)
}
when ODIN_ARCH == .amd64 {
@(require_results, enable_target_feature="sse")
_mm_cvtss_si64 :: #force_inline proc "c"(a: __m128) -> i64 {
return cvtss2si64(a)
}
@(require_results, enable_target_feature="sse")
_mm_cvttss_si64 :: #force_inline proc "c"(a: __m128) -> i64 {
return cvttss2si64(a)
}
@(require_results, enable_target_feature="sse")
_mm_cvtsi64_ss :: #force_inline proc "c"(a: __m128, b: i64) -> __m128 {
return cvtsi642ss(a, b)
}
}
@(private, default_calling_convention="c")
foreign _ {
@(link_name="llvm.x86.sse.add.ss")
addss :: proc(a, b: __m128) -> __m128 ---
@(link_name="llvm.x86.sse.sub.ss")
subss :: proc(a, b: __m128) -> __m128 ---
@(link_name="llvm.x86.sse.mul.ss")
mulss :: proc(a, b: __m128) -> __m128 ---
@(link_name="llvm.x86.sse.div.ss")
divss :: proc(a, b: __m128) -> __m128 ---
@(link_name="llvm.x86.sse.sqrt.ss")
sqrtss :: proc(a: __m128) -> __m128 ---
@(link_name="llvm.x86.sse.sqrt.ps")
sqrtps :: proc(a: __m128) -> __m128 ---
@(link_name="llvm.x86.sse.rcp.ss")
rcpss :: proc(a: __m128) -> __m128 ---
@(link_name="llvm.x86.sse.rcp.ps")
rcpps :: proc(a: __m128) -> __m128 ---
@(link_name="llvm.x86.sse.rsqrt.ss")
rsqrtss :: proc(a: __m128) -> __m128 ---
@(link_name="llvm.x86.sse.rsqrt.ps")
rsqrtps :: proc(a: __m128) -> __m128 ---
@(link_name="llvm.x86.sse.min.ss")
minss :: proc(a, b: __m128) -> __m128 ---
@(link_name="llvm.x86.sse.min.ps")
minps :: proc(a, b: __m128) -> __m128 ---
@(link_name="llvm.x86.sse.max.ss")
maxss :: proc(a, b: __m128) -> __m128 ---
@(link_name="llvm.x86.sse.max.ps")
maxps :: proc(a, b: __m128) -> __m128 ---
@(link_name="llvm.x86.sse.movmsk.ps")
movmskps :: proc(a: __m128) -> u32 ---
@(link_name="llvm.x86.sse.cmp.ps")
cmpps :: proc(a, b: __m128, #const imm8: u8) -> __m128 ---
@(link_name="llvm.x86.sse.comieq.ss")
comieq_ss :: proc(a, b: __m128) -> b32 ---
@(link_name="llvm.x86.sse.comilt.ss")
comilt_ss :: proc(a, b: __m128) -> b32 ---
@(link_name="llvm.x86.sse.comile.ss")
comile_ss :: proc(a, b: __m128) -> b32 ---
@(link_name="llvm.x86.sse.comigt.ss")
comigt_ss :: proc(a, b: __m128) -> b32 ---
@(link_name="llvm.x86.sse.comige.ss")
comige_ss :: proc(a, b: __m128) -> b32 ---
@(link_name="llvm.x86.sse.comineq.ss")
comineq_ss :: proc(a, b: __m128) -> b32 ---
@(link_name="llvm.x86.sse.ucomieq.ss")
ucomieq_ss :: proc(a, b: __m128) -> b32 ---
@(link_name="llvm.x86.sse.ucomilt.ss")
ucomilt_ss :: proc(a, b: __m128) -> b32 ---
@(link_name="llvm.x86.sse.ucomile.ss")
ucomile_ss :: proc(a, b: __m128) -> b32 ---
@(link_name="llvm.x86.sse.ucomigt.ss")
ucomigt_ss :: proc(a, b: __m128) -> b32 ---
@(link_name="llvm.x86.sse.ucomige.ss")
ucomige_ss :: proc(a, b: __m128) -> b32 ---
@(link_name="llvm.x86.sse.ucomineq.ss")
ucomineq_ss :: proc(a, b: __m128) -> b32 ---
@(link_name="llvm.x86.sse.cvtss2si")
cvtss2si :: proc(a: __m128) -> i32 ---
@(link_name="llvm.x86.sse.cvttss2si")
cvttss2si :: proc(a: __m128) -> i32 ---
@(link_name="llvm.x86.sse.cvtsi2ss")
cvtsi2ss :: proc(a: __m128, b: i32) -> __m128 ---
@(link_name="llvm.x86.sse.sfence")
sfence :: proc() ---
@(link_name="llvm.x86.sse.stmxcsr")
stmxcsr :: proc(p: rawptr) ---
@(link_name="llvm.x86.sse.ldmxcsr")
ldmxcsr :: proc(p: rawptr) ---
@(link_name="llvm.prefetch")
prefetch :: proc(p: rawptr, #const rw, loc, ty: u32) ---
@(link_name="llvm.x86.sse.cmp.ss")
cmpss :: proc(a, b: __m128, #const imm8: u8) -> __m128 ---
// amd64 only
@(link_name="llvm.x86.sse.cvtss2si64")
cvtss2si64 :: proc(a: __m128) -> i64 ---
@(link_name="llvm.x86.sse.cvttss2si64")
cvttss2si64 :: proc(a: __m128) -> i64 ---
@(link_name="llvm.x86.sse.cvtsi642ss")
cvtsi642ss :: proc(a: __m128, b: i64) -> __m128 ---
}
File diff suppressed because it is too large Load Diff
+68
View File
@@ -0,0 +1,68 @@
//+build i386, amd64
package simd_x86
import "core:intrinsics"
import "core:simd"
@(require_results, enable_target_feature="sse3")
_mm_addsub_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return addsubps(a, b)
}
@(require_results, enable_target_feature="sse3")
_mm_addsub_pd :: #force_inline proc "c" (a: __m128d, b: __m128d) -> __m128d {
return addsubpd(a, b)
}
@(require_results, enable_target_feature="sse3")
_mm_hadd_pd :: #force_inline proc "c" (a: __m128d, b: __m128d) -> __m128d {
return haddpd(a, b)
}
@(require_results, enable_target_feature="sse3")
_mm_hadd_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return haddps(a, b)
}
@(require_results, enable_target_feature="sse3")
_mm_hsub_pd :: #force_inline proc "c" (a: __m128d, b: __m128d) -> __m128d {
return hsubpd(a, b)
}
@(require_results, enable_target_feature="sse3")
_mm_hsub_ps :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return hsubps(a, b)
}
@(require_results, enable_target_feature="sse3")
_mm_lddqu_si128 :: #force_inline proc "c" (mem_addr: ^__m128i) -> __m128i {
return transmute(__m128i)lddqu(mem_addr)
}
@(require_results, enable_target_feature="sse3")
_mm_movedup_pd :: #force_inline proc "c" (a: __m128d) -> __m128d {
return simd.shuffle(a, a, 0, 0)
}
@(require_results, enable_target_feature="sse3")
_mm_loaddup_pd :: #force_inline proc "c" (mem_addr: [^]f64) -> __m128d {
return _mm_load1_pd(mem_addr)
}
@(require_results, enable_target_feature="sse3")
_mm_movehdup_ps :: #force_inline proc "c" (a: __m128) -> __m128 {
return simd.shuffle(a, a, 1, 1, 3, 3)
}
@(require_results, enable_target_feature="sse3")
_mm_moveldup_ps :: #force_inline proc "c" (a: __m128) -> __m128 {
return simd.shuffle(a, a, 0, 0, 2, 2)
}
@(private, default_calling_convention="c")
foreign _ {
@(link_name = "llvm.x86.sse3.addsub.ps")
addsubps :: proc(a, b: __m128) -> __m128 ---
@(link_name = "llvm.x86.sse3.addsub.pd")
addsubpd :: proc(a: __m128d, b: __m128d) -> __m128d ---
@(link_name = "llvm.x86.sse3.hadd.pd")
haddpd :: proc(a: __m128d, b: __m128d) -> __m128d ---
@(link_name = "llvm.x86.sse3.hadd.ps")
haddps :: proc(a, b: __m128) -> __m128 ---
@(link_name = "llvm.x86.sse3.hsub.pd")
hsubpd :: proc(a: __m128d, b: __m128d) -> __m128d ---
@(link_name = "llvm.x86.sse3.hsub.ps")
hsubps :: proc(a, b: __m128) -> __m128 ---
@(link_name = "llvm.x86.sse3.ldu.dq")
lddqu :: proc(mem_addr: rawptr) -> i8x16 ---
}
+352
View File
@@ -0,0 +1,352 @@
//+build i386, amd64
package simd_x86
import "core:simd"
// SSE4 rounding constants
_MM_FROUND_TO_NEAREST_INT :: 0x00
_MM_FROUND_TO_NEG_INF :: 0x01
_MM_FROUND_TO_POS_INF :: 0x02
_MM_FROUND_TO_ZERO :: 0x03
_MM_FROUND_CUR_DIRECTION :: 0x04
_MM_FROUND_RAISE_EXC :: 0x00
_MM_FROUND_NO_EXC :: 0x08
_MM_FROUND_NINT :: 0x00
_MM_FROUND_FLOOR :: _MM_FROUND_RAISE_EXC | _MM_FROUND_TO_NEG_INF
_MM_FROUND_CEIL :: _MM_FROUND_RAISE_EXC | _MM_FROUND_TO_POS_INF
_MM_FROUND_TRUNC :: _MM_FROUND_RAISE_EXC | _MM_FROUND_TO_ZERO
_MM_FROUND_RINT :: _MM_FROUND_RAISE_EXC | _MM_FROUND_CUR_DIRECTION
_MM_FROUND_NEARBYINT :: _MM_FROUND_NO_EXC | _MM_FROUND_CUR_DIRECTION
@(require_results, enable_target_feature="sse4.1")
_mm_blendv_epi8 :: #force_inline proc "c" (a, b, mask: __m128i) -> __m128i {
return transmute(__m128i)pblendvb(transmute(i8x16)a, transmute(i8x16)b, transmute(i8x16)mask)
}
@(require_results, enable_target_feature="sse4.1")
_mm_blend_epi16 :: #force_inline proc "c" (a, b: __m128i, $IMM8: u8) -> __m128i {
return transmute(__m128i)pblendw(transmute(i16x8)a, transmute(i16x8)b, IMM8)
}
@(require_results, enable_target_feature="sse4.1")
_mm_blendv_pd :: #force_inline proc "c" (a, b, mask: __m128d) -> __m128d {
return blendvpd(a, b, mask)
}
@(require_results, enable_target_feature="sse4.1")
_mm_blendv_ps :: #force_inline proc "c" (a, b, mask: __m128) -> __m128 {
return blendvps(a, b, mask)
}
@(require_results, enable_target_feature="sse4.1")
_mm_blend_pd :: #force_inline proc "c" (a, b: __m128d, $IMM2: u8) -> __m128d {
return blendpd(a, b, IMM2)
}
@(require_results, enable_target_feature="sse4.1")
_mm_blend_ps :: #force_inline proc "c" (a, b: __m128, $IMM4: u8) -> __m128 {
return blendps(a, b, IMM4)
}
@(require_results, enable_target_feature="sse4.1")
_mm_extract_ps :: #force_inline proc "c" (a: __m128, $IMM8: u32) -> i32 {
return transmute(i32)simd.extract(a, IMM8)
}
@(require_results, enable_target_feature="sse4.1")
_mm_extract_epi8 :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> i32 {
return i32(simd.extract(transmute(u8x16)a, IMM8))
}
@(require_results, enable_target_feature="sse4.1")
_mm_extract_epi32 :: #force_inline proc "c" (a: __m128i, $IMM8: u32) -> i32 {
return simd.extract(transmute(i32x4)a, IMM8)
}
@(require_results, enable_target_feature="sse4.1")
_mm_insert_ps :: #force_inline proc "c" (a, b: __m128, $IMM8: u8) -> __m128 {
return insertps(a, b, IMM8)
}
@(require_results, enable_target_feature="sse4.1")
_mm_insert_epi8 :: #force_inline proc "c" (a: __m128i, i: i32, $IMM8: u32) -> __m128i {
return transmute(__m128i)simd.replace(transmute(i8x16)a, IMM8, i8(i))
}
@(require_results, enable_target_feature="sse4.1")
_mm_insert_epi32 :: #force_inline proc "c" (a: __m128i, i: i32, $IMM8: u32) -> __m128i {
return transmute(__m128i)simd.replace(transmute(i32x4)a, IMM8, i)
}
@(require_results, enable_target_feature="sse4.1")
_mm_max_epi8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)pmaxsb(transmute(i8x16)a, transmute(i8x16)b)
}
@(require_results, enable_target_feature="sse4.1")
_mm_max_epu16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)pmaxuw(transmute(u16x8)a, transmute(u16x8)b)
}
@(require_results, enable_target_feature="sse4.1")
_mm_max_epi32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)pmaxsd(transmute(i32x4)a, transmute(i32x4)b)
}
@(require_results, enable_target_feature="sse4.1")
_mm_max_epu32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)pmaxud(transmute(u32x4)a, transmute(u32x4)b)
}
@(require_results, enable_target_feature="sse4.1")
_mm_min_epi8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)pminsb(transmute(i8x16)a, transmute(i8x16)b)
}
@(require_results, enable_target_feature="sse4.1")
_mm_min_epu16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)pminuw(transmute(u16x8)a, transmute(u16x8)b)
}
@(require_results, enable_target_feature="sse4.1")
_mm_min_epi32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)pminsd(transmute(i32x4)a, transmute(i32x4)b)
}
@(require_results, enable_target_feature="sse4.1")
_mm_min_epu32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)pminud(transmute(u32x4)a, transmute(u32x4)b)
}
@(require_results, enable_target_feature="sse4.1")
_mm_packus_epi32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)packusdw(transmute(i32x4)a, transmute(i32x4)b)
}
@(require_results, enable_target_feature="sse4.1")
_mm_cmpeq_epi64 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)simd.lanes_eq(transmute(i64x2)a, transmute(i64x2)b)
}
@(require_results, enable_target_feature="sse4.1")
_mm_cvtepi8_epi16 :: #force_inline proc "c" (a: __m128i) -> __m128i {
x := transmute(i8x16)a
y := simd.shuffle(x, x, 0, 1, 2, 3, 4, 5, 6, 7)
return transmute(__m128i)i16x8(y)
}
@(require_results, enable_target_feature="sse4.1")
_mm_cvtepi8_epi32 :: #force_inline proc "c" (a: __m128i) -> __m128i {
x := transmute(i8x16)a
y := simd.shuffle(x, x, 0, 1, 2, 3)
return transmute(__m128i)i32x4(y)
}
@(require_results, enable_target_feature="sse4.1")
_mm_cvtepi8_epi64 :: #force_inline proc "c" (a: __m128i) -> __m128i {
x := transmute(i8x16)a
y := simd.shuffle(x, x, 0, 1)
return transmute(__m128i)i64x2(y)
}
@(require_results, enable_target_feature="sse4.1")
_mm_cvtepi16_epi32 :: #force_inline proc "c" (a: __m128i) -> __m128i {
x := transmute(i16x8)a
y := simd.shuffle(x, x, 0, 1, 2, 3)
return transmute(__m128i)i32x4(y)
}
@(require_results, enable_target_feature="sse4.1")
_mm_cvtepi16_epi64 :: #force_inline proc "c" (a: __m128i) -> __m128i {
x := transmute(i16x8)a
y := simd.shuffle(x, x, 0, 1)
return transmute(__m128i)i64x2(y)
}
@(require_results, enable_target_feature="sse4.1")
_mm_cvtepi32_epi64 :: #force_inline proc "c" (a: __m128i) -> __m128i {
x := transmute(i32x4)a
y := simd.shuffle(x, x, 0, 1)
return transmute(__m128i)i64x2(y)
}
@(require_results, enable_target_feature="sse4.1")
_mm_cvtepu8_epi16 :: #force_inline proc "c" (a: __m128i) -> __m128i {
x := transmute(u8x16)a
y := simd.shuffle(x, x, 0, 1, 2, 3, 4, 5, 6, 7)
return transmute(__m128i)i16x8(y)
}
@(require_results, enable_target_feature="sse4.1")
_mm_cvtepu8_epi32 :: #force_inline proc "c" (a: __m128i) -> __m128i {
x := transmute(u8x16)a
y := simd.shuffle(x, x, 0, 1, 2, 3)
return transmute(__m128i)i32x4(y)
}
@(require_results, enable_target_feature="sse4.1")
_mm_cvtepu8_epi64 :: #force_inline proc "c" (a: __m128i) -> __m128i {
x := transmute(u8x16)a
y := simd.shuffle(x, x, 0, 1)
return transmute(__m128i)i64x2(y)
}
@(require_results, enable_target_feature="sse4.1")
_mm_cvtepu16_epi32 :: #force_inline proc "c" (a: __m128i) -> __m128i {
x := transmute(u16x8)a
y := simd.shuffle(x, x, 0, 1, 2, 3)
return transmute(__m128i)i32x4(y)
}
@(require_results, enable_target_feature="sse4.1")
_mm_cvtepu16_epi64 :: #force_inline proc "c" (a: __m128i) -> __m128i {
x := transmute(u16x8)a
y := simd.shuffle(x, x, 0, 1)
return transmute(__m128i)i64x2(y)
}
@(require_results, enable_target_feature="sse4.1")
_mm_cvtepu32_epi64 :: #force_inline proc "c" (a: __m128i) -> __m128i {
x := transmute(u32x4)a
y := simd.shuffle(x, x, 0, 1)
return transmute(__m128i)i64x2(y)
}
@(require_results, enable_target_feature="sse4.1")
_mm_dp_pd :: #force_inline proc "c" (a, b: __m128d, $IMM8: u8) -> __m128d {
return dppd(a, b, IMM8)
}
@(require_results, enable_target_feature="sse4.1")
_mm_dp_ps :: #force_inline proc "c" (a, b: __m128, $IMM8: u8) -> __m128 {
return dpps(a, b, IMM8)
}
@(require_results, enable_target_feature="sse4.1")
_mm_floor_pd :: #force_inline proc "c" (a: __m128d) -> __m128d {
return simd.floor(a)
}
@(require_results, enable_target_feature="sse4.1")
_mm_floor_ps :: #force_inline proc "c" (a: __m128) -> __m128 {
return simd.floor(a)
}
@(require_results, enable_target_feature="sse4.1")
_mm_floor_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d {
return roundsd(a, b, _MM_FROUND_FLOOR)
}
@(require_results, enable_target_feature="sse4.1")
_mm_floor_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return roundss(a, b, _MM_FROUND_FLOOR)
}
@(require_results, enable_target_feature="sse4.1")
_mm_ceil_pd :: #force_inline proc "c" (a: __m128d) -> __m128d {
return simd.ceil(a)
}
@(require_results, enable_target_feature="sse4.1")
_mm_ceil_ps :: #force_inline proc "c" (a: __m128) -> __m128 {
return simd.ceil(a)
}
@(require_results, enable_target_feature="sse4.1")
_mm_ceil_sd :: #force_inline proc "c" (a, b: __m128d) -> __m128d {
return roundsd(a, b, _MM_FROUND_CEIL)
}
@(require_results, enable_target_feature="sse4.1")
_mm_ceil_ss :: #force_inline proc "c" (a, b: __m128) -> __m128 {
return roundss(a, b, _MM_FROUND_CEIL)
}
@(require_results, enable_target_feature="sse4.1")
_mm_round_pd :: #force_inline proc "c" (a: __m128d, $ROUNDING: i32) -> __m128d {
return roundpd(a, ROUNDING)
}
@(require_results, enable_target_feature="sse4.1")
_mm_round_ps :: #force_inline proc "c" (a: __m128, $ROUNDING: i32) -> __m128 {
return roundps(a, ROUNDING)
}
@(require_results, enable_target_feature="sse4.1")
_mm_round_sd :: #force_inline proc "c" (a, b: __m128d, $ROUNDING: i32) -> __m128d {
return roundsd(a, b, ROUNDING)
}
@(require_results, enable_target_feature="sse4.1")
_mm_round_ss :: #force_inline proc "c" (a, b: __m128, $ROUNDING: i32) -> __m128 {
return roundss(a, b, ROUNDING)
}
@(require_results, enable_target_feature="sse4.1")
_mm_minpos_epu16 :: #force_inline proc "c" (a: __m128i) -> __m128i {
return transmute(__m128i)phminposuw(transmute(u16x8)a)
}
@(require_results, enable_target_feature="sse4.1")
_mm_mul_epi32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)pmuldq(transmute(i32x4)a, transmute(i32x4)b)
}
@(require_results, enable_target_feature="sse4.1")
_mm_mullo_epi32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)simd.mul(transmute(i32x4)a, transmute(i32x4)b)
}
@(require_results, enable_target_feature="sse4.1")
_mm_mpsadbw_epu8 :: #force_inline proc "c" (a, b: __m128i, $IMM8: u8) -> __m128i {
return transmute(__m128i)mpsadbw(transmute(u8x16)a, transmute(u8x16)b, IMM8)
}
@(require_results, enable_target_feature="sse4.1")
_mm_testz_si128 :: #force_inline proc "c" (a: __m128i, mask: __m128i) -> i32 {
return ptestz(transmute(i64x2)a, transmute(i64x2)mask)
}
@(require_results, enable_target_feature="sse4.1")
_mm_testc_si128 :: #force_inline proc "c" (a: __m128i, mask: __m128i) -> i32 {
return ptestc(transmute(i64x2)a, transmute(i64x2)mask)
}
@(require_results, enable_target_feature="sse4.1")
_mm_testnzc_si128 :: #force_inline proc "c" (a: __m128i, mask: __m128i) -> i32 {
return ptestnzc(transmute(i64x2)a, transmute(i64x2)mask)
}
@(require_results, enable_target_feature="sse4.1")
_mm_test_all_zeros :: #force_inline proc "c" (a: __m128i, mask: __m128i) -> i32 {
return _mm_testz_si128(a, mask)
}
@(require_results, enable_target_feature="sse4.1")
_mm_test_all_ones :: #force_inline proc "c" (a: __m128i) -> i32 {
return _mm_testc_si128(a, _mm_cmpeq_epi32(a, a))
}
@(require_results, enable_target_feature="sse4.1")
_mm_test_mix_ones_zeros :: #force_inline proc "c" (a: __m128i, mask: __m128i) -> i32 {
return _mm_testnzc_si128(a, mask)
}
when ODIN_ARCH == .amd64 {
@(require_results, enable_target_feature="sse4.1")
_mm_extract_epi64 :: #force_inline proc "c" (a: __m128i, $IMM1: u32) -> i64 {
return simd.extract(transmute(i64x2)a, IMM1)
}
@(require_results, enable_target_feature="sse4.1")
_mm_insert_epi64 :: #force_inline proc "c" (a: __m128i, i: i64, $IMM1: u32) -> __m128i {
return transmute(__m128i)simd.replace(transmute(i64x2)a, IMM1, i)
}
}
@(private, default_calling_convention="c")
foreign _ {
@(link_name = "llvm.x86.sse41.pblendvb")
pblendvb :: proc(a, b: i8x16, mask: i8x16) -> i8x16 ---
@(link_name = "llvm.x86.sse41.blendvpd")
blendvpd :: proc(a, b, mask: __m128d) -> __m128d ---
@(link_name = "llvm.x86.sse41.blendvps")
blendvps :: proc(a, b, mask: __m128) -> __m128 ---
@(link_name = "llvm.x86.sse41.blendpd")
blendpd :: proc(a, b: __m128d, #const imm2: u8) -> __m128d ---
@(link_name = "llvm.x86.sse41.blendps")
blendps :: proc(a, b: __m128, #const imm4: u8) -> __m128 ---
@(link_name = "llvm.x86.sse41.pblendw")
pblendw :: proc(a: i16x8, b: i16x8, #const imm8: u8) -> i16x8 ---
@(link_name = "llvm.x86.sse41.insertps")
insertps :: proc(a, b: __m128, #const imm8: u8) -> __m128 ---
@(link_name = "llvm.x86.sse41.pmaxsb")
pmaxsb :: proc(a, b: i8x16) -> i8x16 ---
@(link_name = "llvm.x86.sse41.pmaxuw")
pmaxuw :: proc(a, b: u16x8) -> u16x8 ---
@(link_name = "llvm.x86.sse41.pmaxsd")
pmaxsd :: proc(a, b: i32x4) -> i32x4 ---
@(link_name = "llvm.x86.sse41.pmaxud")
pmaxud :: proc(a, b: u32x4) -> u32x4 ---
@(link_name = "llvm.x86.sse41.pminsb")
pminsb :: proc(a, b: i8x16) -> i8x16 ---
@(link_name = "llvm.x86.sse41.pminuw")
pminuw :: proc(a, b: u16x8) -> u16x8 ---
@(link_name = "llvm.x86.sse41.pminsd")
pminsd :: proc(a, b: i32x4) -> i32x4 ---
@(link_name = "llvm.x86.sse41.pminud")
pminud :: proc(a, b: u32x4) -> u32x4 ---
@(link_name = "llvm.x86.sse41.packusdw")
packusdw :: proc(a, b: i32x4) -> u16x8 ---
@(link_name = "llvm.x86.sse41.dppd")
dppd :: proc(a, b: __m128d, #const imm8: u8) -> __m128d ---
@(link_name = "llvm.x86.sse41.dpps")
dpps :: proc(a, b: __m128, #const imm8: u8) -> __m128 ---
@(link_name = "llvm.x86.sse41.round.pd")
roundpd :: proc(a: __m128d, rounding: i32) -> __m128d ---
@(link_name = "llvm.x86.sse41.round.ps")
roundps :: proc(a: __m128, rounding: i32) -> __m128 ---
@(link_name = "llvm.x86.sse41.round.sd")
roundsd :: proc(a, b: __m128d, rounding: i32) -> __m128d ---
@(link_name = "llvm.x86.sse41.round.ss")
roundss :: proc(a, b: __m128, rounding: i32) -> __m128 ---
@(link_name = "llvm.x86.sse41.phminposuw")
phminposuw :: proc(a: u16x8) -> u16x8 ---
@(link_name = "llvm.x86.sse41.pmuldq")
pmuldq :: proc(a, b: i32x4) -> i64x2 ---
@(link_name = "llvm.x86.sse41.mpsadbw")
mpsadbw :: proc(a, b: u8x16, #const imm8: u8) -> u16x8 ---
@(link_name = "llvm.x86.sse41.ptestz")
ptestz :: proc(a, mask: i64x2) -> i32 ---
@(link_name = "llvm.x86.sse41.ptestc")
ptestc :: proc(a, mask: i64x2) -> i32 ---
@(link_name = "llvm.x86.sse41.ptestnzc")
ptestnzc :: proc(a, mask: i64x2) -> i32 ---
}
+149
View File
@@ -0,0 +1,149 @@
//+build i386, amd64
package simd_x86
import "core:simd"
_SIDD_UBYTE_OPS :: 0b0000_0000
_SIDD_UWORD_OPS :: 0b0000_0001
_SIDD_SBYTE_OPS :: 0b0000_0010
_SIDD_SWORD_OPS :: 0b0000_0011
_SIDD_CMP_EQUAL_ANY :: 0b0000_0000
_SIDD_CMP_RANGES :: 0b0000_0100
_SIDD_CMP_EQUAL_EACH :: 0b0000_1000
_SIDD_CMP_EQUAL_ORDERED :: 0b0000_1100
_SIDD_POSITIVE_POLARITY :: 0b0000_0000
_SIDD_NEGATIVE_POLARITY :: 0b0001_0000
_SIDD_MASKED_POSITIVE_POLARITY :: 0b0010_0000
_SIDD_MASKED_NEGATIVE_POLARITY :: 0b0011_0000
_SIDD_LEAST_SIGNIFICANT :: 0b0000_0000
_SIDD_MOST_SIGNIFICANT :: 0b0100_0000
_SIDD_BIT_MASK :: 0b0000_0000
_SIDD_UNIT_MASK :: 0b0100_0000
@(require_results, enable_target_feature="sse4.2")
_mm_cmpistrm :: #force_inline proc "c" (a: __m128i, b: __m128i, $IMM8: i8) -> __m128i {
return transmute(__m128i)pcmpistrm128(transmute(i8x16)a, transmute(i8x16)b, IMM8)
}
@(require_results, enable_target_feature="sse4.2")
_mm_cmpistri :: #force_inline proc "c" (a: __m128i, b: __m128i, $IMM8: i8) -> i32 {
return pcmpistri128(transmute(i8x16)a, transmute(i8x16)b, IMM8)
}
@(require_results, enable_target_feature="sse4.2")
_mm_cmpistrz :: #force_inline proc "c" (a: __m128i, b: __m128i, $IMM8: i8) -> i32 {
return pcmpistriz128(transmute(i8x16)a, transmute(i8x16)b, IMM8)
}
@(require_results, enable_target_feature="sse4.2")
_mm_cmpistrc :: #force_inline proc "c" (a: __m128i, b: __m128i, $IMM8: i8) -> i32 {
return pcmpistric128(transmute(i8x16)a, transmute(i8x16)b, IMM8)
}
@(require_results, enable_target_feature="sse4.2")
_mm_cmpistrs :: #force_inline proc "c" (a: __m128i, b: __m128i, $IMM8: i8) -> i32 {
return pcmpistris128(transmute(i8x16)a, transmute(i8x16)b, IMM8)
}
@(require_results, enable_target_feature="sse4.2")
_mm_cmpistro :: #force_inline proc "c" (a: __m128i, b: __m128i, $IMM8: i8) -> i32 {
return pcmpistrio128(transmute(i8x16)a, transmute(i8x16)b, IMM8)
}
@(require_results, enable_target_feature="sse4.2")
_mm_cmpistra :: #force_inline proc "c" (a: __m128i, b: __m128i, $IMM8: i8) -> i32 {
return pcmpistria128(transmute(i8x16)a, transmute(i8x16)b, IMM8)
}
@(require_results, enable_target_feature="sse4.2")
_mm_cmpestrm :: #force_inline proc "c" (a: __m128i, la: i32, b: __m128i, lb: i32, $IMM8: i8) -> __m128i {
return transmute(__m128i)pcmpestrm128(transmute(i8x16)a, la, transmute(i8x16)b, lb, IMM8)
}
@(require_results, enable_target_feature="sse4.2")
_mm_cmpestri :: #force_inline proc "c" (a: __m128i, la: i32, b: __m128i, lb: i32, $IMM8: i8) -> i32 {
return pcmpestri128(transmute(i8x16)a, la, transmute(i8x16)b, lb, IMM8)
}
@(require_results, enable_target_feature="sse4.2")
_mm_cmpestrz :: #force_inline proc "c" (a: __m128i, la: i32, b: __m128i, lb: i32, $IMM8: i8) -> i32 {
return pcmpestriz128(transmute(i8x16)a, la, transmute(i8x16)b, lb, IMM8)
}
@(require_results, enable_target_feature="sse4.2")
_mm_cmpestrc :: #force_inline proc "c" (a: __m128i, la: i32, b: __m128i, lb: i32, $IMM8: i8) -> i32 {
return pcmpestric128(transmute(i8x16)a, la, transmute(i8x16)b, lb, IMM8)
}
@(require_results, enable_target_feature="sse4.2")
_mm_cmpestrs :: #force_inline proc "c" (a: __m128i, la: i32, b: __m128i, lb: i32, $IMM8: i8) -> i32 {
return pcmpestris128(transmute(i8x16)a, la, transmute(i8x16)b, lb, IMM8)
}
@(require_results, enable_target_feature="sse4.2")
_mm_cmpestro :: #force_inline proc "c" (a: __m128i, la: i32, b: __m128i, lb: i32, $IMM8: i8) -> i32 {
return pcmpestrio128(transmute(i8x16)a, la, transmute(i8x16)b, lb, IMM8)
}
@(require_results, enable_target_feature="sse4.2")
_mm_cmpestra :: #force_inline proc "c" (a: __m128i, la: i32, b: __m128i, lb: i32, $IMM8: i8) -> i32 {
return pcmpestria128(transmute(i8x16)a, la, transmute(i8x16)b, lb, IMM8)
}
@(require_results, enable_target_feature="sse4.2")
_mm_crc32_u8 :: #force_inline proc "c" (crc: u32, v: u8) -> u32 {
return crc32_32_8(crc, v)
}
@(require_results, enable_target_feature="sse4.2")
_mm_crc32_u16 :: #force_inline proc "c" (crc: u32, v: u16) -> u32 {
return crc32_32_16(crc, v)
}
@(require_results, enable_target_feature="sse4.2")
_mm_crc32_u32 :: #force_inline proc "c" (crc: u32, v: u32) -> u32 {
return crc32_32_32(crc, v)
}
@(require_results, enable_target_feature="sse4.2")
_mm_cmpgt_epi64 :: #force_inline proc "c" (a: __m128i, b: __m128i) -> __m128i {
return transmute(__m128i)simd.lanes_gt(transmute(i64x2)a, transmute(i64x2)b)
}
when ODIN_ARCH == .amd64 {
@(require_results, enable_target_feature="sse4.2")
_mm_crc32_u64 :: #force_inline proc "c" (crc: u64, v: u64) -> u64 {
return crc32_64_64(crc, v)
}
}
@(private, default_calling_convention="c")
foreign _ {
// SSE 4.2 string and text comparison ops
@(link_name="llvm.x86.sse42.pcmpestrm128")
pcmpestrm128 :: proc(a: i8x16, la: i32, b: i8x16, lb: i32, #const imm8: i8) -> u8x16 ---
@(link_name="llvm.x86.sse42.pcmpestri128")
pcmpestri128 :: proc(a: i8x16, la: i32, b: i8x16, lb: i32, #const imm8: i8) -> i32 ---
@(link_name="llvm.x86.sse42.pcmpestriz128")
pcmpestriz128 :: proc(a: i8x16, la: i32, b: i8x16, lb: i32, #const imm8: i8) -> i32 ---
@(link_name="llvm.x86.sse42.pcmpestric128")
pcmpestric128 :: proc(a: i8x16, la: i32, b: i8x16, lb: i32, #const imm8: i8) -> i32 ---
@(link_name="llvm.x86.sse42.pcmpestris128")
pcmpestris128 :: proc(a: i8x16, la: i32, b: i8x16, lb: i32, #const imm8: i8) -> i32 ---
@(link_name="llvm.x86.sse42.pcmpestrio128")
pcmpestrio128 :: proc(a: i8x16, la: i32, b: i8x16, lb: i32, #const imm8: i8) -> i32 ---
@(link_name="llvm.x86.sse42.pcmpestria128")
pcmpestria128 :: proc(a: i8x16, la: i32, b: i8x16, lb: i32, #const imm8: i8) -> i32 ---
@(link_name="llvm.x86.sse42.pcmpistrm128")
pcmpistrm128 :: proc(a, b: i8x16, #const imm8: i8) -> i8x16 ---
@(link_name="llvm.x86.sse42.pcmpistri128")
pcmpistri128 :: proc(a, b: i8x16, #const imm8: i8) -> i32 ---
@(link_name="llvm.x86.sse42.pcmpistriz128")
pcmpistriz128 :: proc(a, b: i8x16, #const imm8: i8) -> i32 ---
@(link_name="llvm.x86.sse42.pcmpistric128")
pcmpistric128 :: proc(a, b: i8x16, #const imm8: i8) -> i32 ---
@(link_name="llvm.x86.sse42.pcmpistris128")
pcmpistris128 :: proc(a, b: i8x16, #const imm8: i8) -> i32 ---
@(link_name="llvm.x86.sse42.pcmpistrio128")
pcmpistrio128 :: proc(a, b: i8x16, #const imm8: i8) -> i32 ---
@(link_name="llvm.x86.sse42.pcmpistria128")
pcmpistria128 :: proc(a, b: i8x16, #const imm8: i8) -> i32 ---
// SSE 4.2 CRC instructions
@(link_name="llvm.x86.sse42.crc32.32.8")
crc32_32_8 :: proc(crc: u32, v: u8) -> u32 ---
@(link_name="llvm.x86.sse42.crc32.32.16")
crc32_32_16 :: proc(crc: u32, v: u16) -> u32 ---
@(link_name="llvm.x86.sse42.crc32.32.32")
crc32_32_32 :: proc(crc: u32, v: u32) -> u32 ---
// AMD64 Only
@(link_name="llvm.x86.sse42.crc32.64.64")
crc32_64_64 :: proc(crc: u64, v: u64) -> u64 ---
}
+140
View File
@@ -0,0 +1,140 @@
//+build i386, amd64
package simd_x86
import "core:intrinsics"
import "core:simd"
_ :: simd
@(require_results, enable_target_feature="ssse3")
_mm_abs_epi8 :: #force_inline proc "c" (a: __m128i) -> __m128i {
return transmute(__m128i)pabsb128(transmute(i8x16)a)
}
@(require_results, enable_target_feature="ssse3")
_mm_abs_epi16 :: #force_inline proc "c" (a: __m128i) -> __m128i {
return transmute(__m128i)pabsw128(transmute(i16x8)a)
}
@(require_results, enable_target_feature="ssse3")
_mm_abs_epi32 :: #force_inline proc "c" (a: __m128i) -> __m128i {
return transmute(__m128i)pabsd128(transmute(i32x4)a)
}
@(require_results, enable_target_feature="ssse3")
_mm_shuffle_epi8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)pshufb128(transmute(u8x16)a, transmute(u8x16)b)
}
@(require_results, enable_target_feature="ssse3")
_mm_alignr_epi8 :: #force_inline proc "c" (a, b: __m128i, $IMM8: u32) -> __m128i {
shift :: IMM8
// If palignr is shifting the pair of vectors more than the size of two
// lanes, emit zero.
if shift > 32 {
return _mm_set1_epi8(0)
}
a, b := a, b
if shift > 16 {
a, b = _mm_set1_epi8(0), a
}
return transmute(__m128i)simd.shuffle(
transmute(i8x16)b,
transmute(i8x16)a,
0 when shift > 32 else shift - 16 + 0 when shift > 16 else shift + 0,
1 when shift > 32 else shift - 16 + 1 when shift > 16 else shift + 1,
2 when shift > 32 else shift - 16 + 2 when shift > 16 else shift + 2,
3 when shift > 32 else shift - 16 + 3 when shift > 16 else shift + 3,
4 when shift > 32 else shift - 16 + 4 when shift > 16 else shift + 4,
5 when shift > 32 else shift - 16 + 5 when shift > 16 else shift + 5,
6 when shift > 32 else shift - 16 + 6 when shift > 16 else shift + 6,
7 when shift > 32 else shift - 16 + 7 when shift > 16 else shift + 7,
8 when shift > 32 else shift - 16 + 8 when shift > 16 else shift + 8,
9 when shift > 32 else shift - 16 + 9 when shift > 16 else shift + 9,
10 when shift > 32 else shift - 16 + 10 when shift > 16 else shift + 10,
11 when shift > 32 else shift - 16 + 11 when shift > 16 else shift + 11,
12 when shift > 32 else shift - 16 + 12 when shift > 16 else shift + 12,
13 when shift > 32 else shift - 16 + 13 when shift > 16 else shift + 13,
14 when shift > 32 else shift - 16 + 14 when shift > 16 else shift + 14,
15 when shift > 32 else shift - 16 + 15 when shift > 16 else shift + 15,
)
}
@(require_results, enable_target_feature="ssse3")
_mm_hadd_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)phaddw128(transmute(i16x8)a, transmute(i16x8)b)
}
@(require_results, enable_target_feature="ssse3")
_mm_hadds_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)phaddsw128(transmute(i16x8)a, transmute(i16x8)b)
}
@(require_results, enable_target_feature="ssse3")
_mm_hadd_epi32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)phaddd128(transmute(i32x4)a, transmute(i32x4)b)
}
@(require_results, enable_target_feature="ssse3")
_mm_hsub_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)phsubw128(transmute(i16x8)a, transmute(i16x8)b)
}
@(require_results, enable_target_feature="ssse3")
_mm_hsubs_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)phsubsw128(transmute(i16x8)a, transmute(i16x8)b)
}
@(require_results, enable_target_feature="ssse3")
_mm_hsub_epi32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)phsubd128(transmute(i32x4)a, transmute(i32x4)b)
}
@(require_results, enable_target_feature="ssse3")
_mm_maddubs_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)pmaddubsw128(transmute(u8x16)a, transmute(i8x16)b)
}
@(require_results, enable_target_feature="ssse3")
_mm_mulhrs_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)pmulhrsw128(transmute(i16x8)a, transmute(i16x8)b)
}
@(require_results, enable_target_feature="ssse3")
_mm_sign_epi8 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)psignb128(transmute(i8x16)a, transmute(i8x16)b)
}
@(require_results, enable_target_feature="ssse3")
_mm_sign_epi16 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)psignw128(transmute(i16x8)a, transmute(i16x8)b)
}
@(require_results, enable_target_feature="ssse3")
_mm_sign_epi32 :: #force_inline proc "c" (a, b: __m128i) -> __m128i {
return transmute(__m128i)psignd128(transmute(i32x4)a, transmute(i32x4)b)
}
@(private, default_calling_convention="c")
foreign _ {
@(link_name = "llvm.x86.ssse3.pabs.b.128")
pabsb128 :: proc(a: i8x16) -> u8x16 ---
@(link_name = "llvm.x86.ssse3.pabs.w.128")
pabsw128 :: proc(a: i16x8) -> u16x8 ---
@(link_name = "llvm.x86.ssse3.pabs.d.128")
pabsd128 :: proc(a: i32x4) -> u32x4 ---
@(link_name = "llvm.x86.ssse3.pshuf.b.128")
pshufb128 :: proc(a, b: u8x16) -> u8x16 ---
@(link_name = "llvm.x86.ssse3.phadd.w.128")
phaddw128 :: proc(a, b: i16x8) -> i16x8 ---
@(link_name = "llvm.x86.ssse3.phadd.sw.128")
phaddsw128 :: proc(a, b: i16x8) -> i16x8 ---
@(link_name = "llvm.x86.ssse3.phadd.d.128")
phaddd128 :: proc(a, b: i32x4) -> i32x4 ---
@(link_name = "llvm.x86.ssse3.phsub.w.128")
phsubw128 :: proc(a, b: i16x8) -> i16x8 ---
@(link_name = "llvm.x86.ssse3.phsub.sw.128")
phsubsw128 :: proc(a, b: i16x8) -> i16x8 ---
@(link_name = "llvm.x86.ssse3.phsub.d.128")
phsubd128 :: proc(a, b: i32x4) -> i32x4 ---
@(link_name = "llvm.x86.ssse3.pmadd.ub.sw.128")
pmaddubsw128 :: proc(a: u8x16, b: i8x16) -> i16x8 ---
@(link_name = "llvm.x86.ssse3.pmul.hr.sw.128")
pmulhrsw128 :: proc(a, b: i16x8) -> i16x8 ---
@(link_name = "llvm.x86.ssse3.psign.b.128")
psignb128 :: proc(a, b: i8x16) -> i8x16 ---
@(link_name = "llvm.x86.ssse3.psign.w.128")
psignw128 :: proc(a, b: i16x8) -> i16x8 ---
@(link_name = "llvm.x86.ssse3.psign.d.128")
psignd128 :: proc(a, b: i32x4) -> i32x4 ---
}
+57
View File
@@ -0,0 +1,57 @@
//+build i386, amd64
package simd_x86
import "core:simd"
bf16 :: u16
__m128i :: #simd[2]i64
__m128 :: #simd[4]f32
__m128d :: #simd[2]f64
__m256i :: #simd[4]i64
__m256 :: #simd[8]f32
__m256d :: #simd[4]f64
__m512i :: #simd[8]i64
__m512 :: #simd[16]f32
__m512d :: #simd[8]f64
__m128bh :: #simd[8]bf16
__m256bh :: #simd[16]bf16
__m512bh :: #simd[32]bf16
/// The `__mmask64` type used in AVX-512 intrinsics, a 64-bit integer
__mmask64 :: u64
/// The `__mmask32` type used in AVX-512 intrinsics, a 32-bit integer
__mmask32 :: u32
/// The `__mmask16` type used in AVX-512 intrinsics, a 16-bit integer
__mmask16 :: u16
/// The `__mmask8` type used in AVX-512 intrinsics, a 8-bit integer
__mmask8 :: u8
/// The `_MM_CMPINT_ENUM` type used to specify comparison operations in AVX-512 intrinsics.
_MM_CMPINT_ENUM :: i32
/// The `MM_MANTISSA_NORM_ENUM` type used to specify mantissa normalized operations in AVX-512 intrinsics.
_MM_MANTISSA_NORM_ENUM :: i32
/// The `MM_MANTISSA_SIGN_ENUM` type used to specify mantissa signed operations in AVX-512 intrinsics.
_MM_MANTISSA_SIGN_ENUM :: i32
_MM_PERM_ENUM :: i32
@(private) u8x16 :: simd.u8x16
@(private) i8x16 :: simd.i8x16
@(private) u16x8 :: simd.u16x8
@(private) i16x8 :: simd.i16x8
@(private) u32x4 :: simd.u32x4
@(private) i32x4 :: simd.i32x4
@(private) u64x2 :: simd.u64x2
@(private) i64x2 :: simd.i64x2
@(private) f32x4 :: simd.f32x4
@(private) f64x2 :: simd.f64x2
-33
View File
@@ -1,33 +0,0 @@
package sys_cpu
Cache_Line_Pad :: struct {_: [_cache_line_size]byte};
initialized: bool;
x86: struct {
_: Cache_Line_Pad,
has_aes: bool, // AES hardware implementation (AES NI)
has_adx: bool, // Multi-precision add-carry instruction extensions
has_avx: bool, // Advanced vector extension
has_avx2: bool, // Advanced vector extension 2
has_bmi1: bool, // Bit manipulation instruction set 1
has_bmi2: bool, // Bit manipulation instruction set 2
has_erms: bool, // Enhanced REP for MOVSB and STOSB
has_fma: bool, // Fused-multiply-add instructions
has_os_xsave: bool, // OS supports XSAVE/XRESTOR for saving/restoring XMM registers.
has_pclmulqdq: bool, // PCLMULQDQ instruction - most often used for AES-GCM
has_popcnt: bool, // Hamming weight instruction POPCNT.
has_rdrand: bool, // RDRAND instruction (on-chip random number generator)
has_rdseed: bool, // RDSEED instruction (on-chip random number generator)
has_sse2: bool, // Streaming SIMD extension 2 (always available on amd64)
has_sse3: bool, // Streaming SIMD extension 3
has_ssse3: bool, // Supplemental streaming SIMD extension 3
has_sse41: bool, // Streaming SIMD extension 4 and 4.1
has_sse42: bool, // Streaming SIMD extension 4 and 4.2
_: Cache_Line_Pad,
};
init :: proc() {
_init();
}
-67
View File
@@ -1,67 +0,0 @@
//+build i386, amd64
package sys_cpu
_cache_line_size :: 64;
cpuid :: proc(ax, cx: u32) -> (eax, ebc, ecx, edx: u32) {
return expand_to_tuple(asm(u32, u32) -> struct{eax, ebc, ecx, edx: u32} {
"cpuid",
"={ax},={bx},={cx},={dx},{ax},{cx}",
}(ax, cx));
}
xgetbv :: proc() -> (eax, edx: u32) {
return expand_to_tuple(asm(u32) -> struct{eax, edx: u32} {
"xgetbv",
"={ax},={dx},{cx}",
}(0));
}
_init :: proc() {
is_set :: proc(hwc: u32, value: u32) -> bool {
return hwc&value != 0;
}
initialized = true;
max_id, _, _, _ := cpuid(0, 0);
if max_id < 1 {
return;
}
_, _, ecx1, edx1 := cpuid(1, 0);
x86.has_sse2 = is_set(26, edx1);
x86.has_sse3 = is_set(0, ecx1);
x86.has_pclmulqdq = is_set(1, ecx1);
x86.has_ssse3 = is_set(9, ecx1);
x86.has_fma = is_set(12, ecx1);
x86.has_sse41 = is_set(19, ecx1);
x86.has_sse42 = is_set(20, ecx1);
x86.has_popcnt = is_set(23, ecx1);
x86.has_aes = is_set(25, ecx1);
x86.has_os_xsave = is_set(27, ecx1);
x86.has_rdrand = is_set(30, ecx1);
os_supports_avx := false;
if x86.has_os_xsave {
eax, _ := xgetbv();
os_supports_avx = is_set(1, eax) && is_set(2, eax);
}
x86.has_avx = is_set(28, ecx1) && os_supports_avx;
if max_id < 7 {
return;
}
_, ebx7, _, _ := cpuid(7, 0);
x86.has_bmi1 = is_set(3, ebx7);
x86.has_avx2 = is_set(5, ebx7) && os_supports_avx;
x86.has_bmi2 = is_set(8, ebx7);
x86.has_erms = is_set(9, ebx7);
x86.has_rdseed = is_set(18, ebx7);
x86.has_adx = is_set(19, ebx7);
}