mirror of
https://github.com/odin-lang/Odin.git
synced 2026-07-17 05:01:04 +00:00
Heavily improve reading and writing to bit fields
This commit is contained in:
@@ -8,10 +8,10 @@ IS_WASM :: ODIN_ARCH == .wasm32 || ODIN_ARCH == .wasm64p32
|
||||
|
||||
@(private)
|
||||
RUNTIME_LINKAGE :: "strong" when ODIN_USE_SEPARATE_MODULES else
|
||||
"internal" when ODIN_NO_ENTRY_POINT && (ODIN_BUILD_MODE == .Static || ODIN_BUILD_MODE == .Dynamic || ODIN_BUILD_MODE == .Object) else
|
||||
"strong" when ODIN_BUILD_MODE == .Dynamic else
|
||||
"strong" when !ODIN_NO_CRT else
|
||||
"internal"
|
||||
"internal" when ODIN_NO_ENTRY_POINT && (ODIN_BUILD_MODE == .Static || ODIN_BUILD_MODE == .Dynamic || ODIN_BUILD_MODE == .Object) else
|
||||
"strong" when ODIN_BUILD_MODE == .Dynamic else
|
||||
"strong" when !ODIN_NO_CRT else
|
||||
"internal"
|
||||
RUNTIME_REQUIRE :: false // !ODIN_TILDE
|
||||
|
||||
@(private)
|
||||
@@ -24,7 +24,7 @@ HAS_HARDWARE_SIMD :: false when (ODIN_ARCH == .amd64 || ODIN_ARCH == .i386) && !
|
||||
true
|
||||
|
||||
// Size of a native SIMD register for the current compilation target
|
||||
NATIVE_SIMD_BIT_WIDTH ::
|
||||
NATIVE_SIMD_BIT_WIDTH ::
|
||||
512 when (ODIN_ARCH == .amd64) && intrinsics.has_target_feature("avx512f") else
|
||||
256 when (ODIN_ARCH == .amd64) && (intrinsics.has_target_feature("avx2") || intrinsics.has_target_feature("avx")) else
|
||||
// Fallback for no hardware SIMD, but also SSE, NEON, SVE, RVV and WASM SIMD128.
|
||||
@@ -1186,7 +1186,7 @@ floattidf :: proc "c" (a: i128) -> f64 {
|
||||
// okay
|
||||
case:
|
||||
a = i128(u128(a) >> u128(sd - (DBL_MANT_DIG+2))) |
|
||||
i128(u128(a) & (~u128(0) >> u128(N + DBL_MANT_DIG+2 - sd)) != 0)
|
||||
i128(u128(a) & (~u128(0) >> u128(N + DBL_MANT_DIG+2 - sd)) != 0)
|
||||
}
|
||||
|
||||
a |= i128((a & 4) != 0)
|
||||
@@ -1202,8 +1202,8 @@ floattidf :: proc "c" (a: i128) -> f64 {
|
||||
}
|
||||
fb: [2]u32
|
||||
fb[1] = (u32(s) & 0x80000000) | // sign
|
||||
(u32(e + 1023) << 20) | // exponent
|
||||
u32((u64(a) >> 32) & 0x000FFFFF) // mantissa-high
|
||||
(u32(e + 1023) << 20) | // exponent
|
||||
u32((u64(a) >> 32) & 0x000FFFFF) // mantissa-high
|
||||
fb[0] = u32(a) // mantissa-low
|
||||
return transmute(f64)fb
|
||||
}
|
||||
@@ -1243,8 +1243,8 @@ floattidf_unsigned :: proc "c" (a: u128) -> f64 {
|
||||
}
|
||||
fb: [2]u32
|
||||
fb[1] = (0) | // sign
|
||||
u32((e + 1023) << 20) | // exponent
|
||||
u32((u64(a) >> 32) & 0x000FFFFF) // mantissa-high
|
||||
u32((e + 1023) << 20) | // exponent
|
||||
u32((u64(a) >> 32) & 0x000FFFFF) // mantissa-high
|
||||
fb[0] = u32(a) // mantissa-low
|
||||
return transmute(f64)fb
|
||||
}
|
||||
@@ -1374,24 +1374,71 @@ fixdfti :: proc "c" (a: u64) -> i128 {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
__write_bits :: proc "contextless" (dst, src: [^]byte, offset: uintptr, size: uintptr) {
|
||||
for i in 0..<size {
|
||||
j := offset+i
|
||||
the_bit := byte((src[i>>3]) & (1<<(i&7)) != 0)
|
||||
dst[j>>3] &~= 1<<(j&7)
|
||||
dst[j>>3] |= the_bit<<(j&7)
|
||||
__copy_bits :: #force_inline proc "contextless" (
|
||||
dst: [^]byte,
|
||||
src: [^]byte,
|
||||
buf_bytes: uintptr,
|
||||
dst_bit: uintptr,
|
||||
src_bit: uintptr,
|
||||
size_bits: uintptr,
|
||||
) #no_bounds_check {
|
||||
src_byte := src_bit >> 3
|
||||
dst_byte := dst_bit >> 3
|
||||
src_shift := src_bit & 7
|
||||
dst_shift := dst_bit & 7
|
||||
src_need_bytes := ((src_shift + size_bits + 7) >> 3)
|
||||
a, b: u64
|
||||
if src_need_bytes <= 4 {
|
||||
a = u64(intrinsics.unaligned_load((^u32)(&src[src_byte])))
|
||||
} else {
|
||||
a = intrinsics.unaligned_load((^u64)(&src[src_byte]))
|
||||
b = intrinsics.unaligned_load((^u64)(&src[src_byte + 8]))
|
||||
}
|
||||
bits := (a >> src_shift) | (b << (64 - src_shift))
|
||||
mask := ~u64(0)
|
||||
if size_bits < 64 {
|
||||
mask = (u64(1) << size_bits) - 1
|
||||
}
|
||||
bits &= mask
|
||||
dst_need_bytes := ((dst_shift + size_bits + 7) >> 3)
|
||||
if dst_shift == 0 {
|
||||
if dst_need_bytes <= 4 {
|
||||
v := u64(intrinsics.unaligned_load((^u32)(&dst[dst_byte])))
|
||||
v = (v & ~mask) | bits
|
||||
intrinsics.unaligned_store((^u32)(&dst[dst_byte]), u32(v))
|
||||
} else {
|
||||
v := intrinsics.unaligned_load((^u64)(&dst[dst_byte]))
|
||||
v = (v & ~mask) | bits
|
||||
intrinsics.unaligned_store((^u64)(&dst[dst_byte]), v)
|
||||
}
|
||||
} else {
|
||||
v0 := intrinsics.unaligned_load((^u64)(&dst[dst_byte]))
|
||||
v1 := intrinsics.unaligned_load((^u64)(&dst[dst_byte + 8]))
|
||||
v0 = (v0 & ~(mask << dst_shift)) | (bits << dst_shift)
|
||||
v1 = (v1 & ~(mask >> (64 - dst_shift))) | (bits >> (64 - dst_shift))
|
||||
intrinsics.unaligned_store((^u64)(&dst[dst_byte]), v0)
|
||||
intrinsics.unaligned_store((^u64)(&dst[dst_byte + 8]), v1)
|
||||
}
|
||||
}
|
||||
|
||||
__read_bits :: proc "contextless" (dst, src: [^]byte, offset: uintptr, size: uintptr) {
|
||||
for j in 0..<size {
|
||||
i := offset+j
|
||||
the_bit := byte((src[i>>3]) & (1<<(i&7)) != 0)
|
||||
dst[j>>3] &~= 1<<(j&7)
|
||||
dst[j>>3] |= the_bit<<(j&7)
|
||||
}
|
||||
__write_bits :: proc "contextless" (dst, src: [^]byte, dst_size_bytes: uintptr, offset_bits: uintptr, size_bits: uintptr) {
|
||||
__copy_bits(dst, src, dst_size_bytes, offset_bits, 0, size_bits)
|
||||
// for i in 0..<size_bits {
|
||||
// j := offset_bits+i
|
||||
// the_bit := byte((src[i>>3]) & (1<<(i&7)) != 0)
|
||||
// dst[j>>3] &~= 1<<(j&7)
|
||||
// dst[j>>3] |= the_bit<<(j&7)
|
||||
// }
|
||||
}
|
||||
|
||||
__read_bits :: proc "contextless" (dst, src: [^]byte, src_size_bytes: uintptr, offset_bits: uintptr, size_bits: uintptr) {
|
||||
__copy_bits(dst, src, src_size_bytes, 0, offset_bits, size_bits)
|
||||
// for j in 0..<size_bits {
|
||||
// i := offset_bits+j
|
||||
// the_bit := byte((src[i>>3]) & (1<<(i&7)) != 0)
|
||||
// dst[j>>3] &~= 1<<(j&7)
|
||||
// dst[j>>3] |= the_bit<<(j&7)
|
||||
// }
|
||||
}
|
||||
|
||||
when .Address in ODIN_SANITIZER_FLAGS {
|
||||
|
||||
Reference in New Issue
Block a user