mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
Implementing the changes from the prior commit, to prepare for the following commit. This also means that zig1 now uses the new value interpret mode, so that adding and removing fields from `std.builtin` types is easier. Signed-off-by: mlugg <mlugg@mlugg.co.uk>
4167 lines
154 KiB
C
4167 lines
154 KiB
C
#undef linux
|
|
|
|
#include <stdarg.h>
|
|
#include <stddef.h>
|
|
|
|
#if defined(_MSC_VER)
|
|
#define zig_msvc
|
|
#elif defined(__clang__)
|
|
#define zig_clang
|
|
#define zig_gnuc
|
|
#elif defined(__GNUC__)
|
|
#define zig_gnuc
|
|
#elif defined(__IBMC__)
|
|
#define zig_xlc
|
|
#elif defined(__TINYC__)
|
|
#define zig_tinyc
|
|
#elif defined(__slimcc__)
|
|
#define zig_slimcc
|
|
#endif
|
|
|
|
#if defined(__aarch64__) || (defined(zig_msvc) && defined(_M_ARM64))
|
|
#define zig_aarch64
|
|
#elif defined(__thumb__) || (defined(zig_msvc) && defined(_M_ARM))
|
|
#define zig_thumb
|
|
#define zig_arm
|
|
#elif defined(__arm__)
|
|
#define zig_arm
|
|
#elif defined(__hexagon__)
|
|
#define zig_hexagon
|
|
#elif defined(__loongarch32)
|
|
#define zig_loongarch32
|
|
#define zig_loongarch
|
|
#elif defined(__loongarch64)
|
|
#define zig_loongarch64
|
|
#define zig_loongarch
|
|
#elif defined(__mips64)
|
|
#define zig_mips64
|
|
#define zig_mips
|
|
#elif defined(__mips__)
|
|
#define zig_mips32
|
|
#define zig_mips
|
|
#elif defined(__powerpc64__)
|
|
#define zig_powerpc64
|
|
#define zig_powerpc
|
|
#elif defined(__powerpc__)
|
|
#define zig_powerpc32
|
|
#define zig_powerpc
|
|
#elif defined(__riscv) && __riscv_xlen == 32
|
|
#define zig_riscv32
|
|
#define zig_riscv
|
|
#elif defined(__riscv) && __riscv_xlen == 64
|
|
#define zig_riscv64
|
|
#define zig_riscv
|
|
#elif defined(__s390x__)
|
|
#define zig_s390x
|
|
#elif defined(__sparc__) && defined(__arch64__)
|
|
#define zig_sparc64
|
|
#define zig_sparc
|
|
#elif defined(__sparc__)
|
|
#define zig_sparc32
|
|
#define zig_sparc
|
|
#elif defined(__wasm32__)
|
|
#define zig_wasm32
|
|
#define zig_wasm
|
|
#elif defined(__wasm64__)
|
|
#define zig_wasm64
|
|
#define zig_wasm
|
|
#elif defined(__i386__) || (defined(zig_msvc) && defined(_M_IX86))
|
|
#define zig_x86_32
|
|
#define zig_x86
|
|
#elif defined (__x86_64__) || (defined(zig_msvc) && defined(_M_X64))
|
|
#define zig_x86_64
|
|
#define zig_x86
|
|
#endif
|
|
|
|
#if defined(zig_msvc) || __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
|
#define zig_little_endian 1
|
|
#define zig_big_endian 0
|
|
#else
|
|
#define zig_little_endian 0
|
|
#define zig_big_endian 1
|
|
#endif
|
|
|
|
#if defined(_AIX)
|
|
#define zig_aix
|
|
#elif defined(__MACH__)
|
|
#define zig_darwin
|
|
#elif defined(__DragonFly__)
|
|
#define zig_dragonfly
|
|
#define zig_bsd
|
|
#elif defined(__EMSCRIPTEN__)
|
|
#define zig_emscripten
|
|
#elif defined(__FreeBSD__)
|
|
#define zig_freebsd
|
|
#define zig_bsd
|
|
#elif defined(__Fuchsia__)
|
|
#define zig_fuchsia
|
|
#elif defined(__HAIKU__)
|
|
#define zig_haiku
|
|
#elif defined(__gnu_hurd__)
|
|
#define zig_hurd
|
|
#elif defined(__linux__)
|
|
#define zig_linux
|
|
#elif defined(__NetBSD__)
|
|
#define zig_netbsd
|
|
#define zig_bsd
|
|
#elif defined(__OpenBSD__)
|
|
#define zig_openbsd
|
|
#define zig_bsd
|
|
#elif defined(__SVR4)
|
|
#define zig_solaris
|
|
#elif defined(__wasi__)
|
|
#define zig_wasi
|
|
#elif defined(_WIN32)
|
|
#define zig_windows
|
|
#elif defined(__MVS__)
|
|
#define zig_zos
|
|
#endif
|
|
|
|
#if defined(zig_windows)
|
|
#define zig_coff
|
|
#elif defined(__ELF__)
|
|
#define zig_elf
|
|
#elif defined(zig_zos)
|
|
#define zig_goff
|
|
#elif defined(zig_darwin)
|
|
#define zig_macho
|
|
#elif defined(zig_aix)
|
|
#define zig_xcoff
|
|
#endif
|
|
|
|
#define zig_concat(lhs, rhs) lhs##rhs
|
|
#define zig_expand_concat(lhs, rhs) zig_concat(lhs, rhs)
|
|
|
|
#if defined(__has_include)
|
|
#define zig_has_include(include) __has_include(include)
|
|
#else
|
|
#define zig_has_include(include) 0
|
|
#endif
|
|
|
|
#if defined(__has_builtin)
|
|
#define zig_has_builtin(builtin) __has_builtin(__builtin_##builtin)
|
|
#else
|
|
#define zig_has_builtin(builtin) 0
|
|
#endif
|
|
#define zig_expand_has_builtin(b) zig_has_builtin(b)
|
|
|
|
#if defined(__has_attribute)
|
|
#define zig_has_attribute(attribute) __has_attribute(attribute)
|
|
#else
|
|
#define zig_has_attribute(attribute) 0
|
|
#endif
|
|
|
|
#if __STDC_VERSION__ >= 202311L
|
|
#define zig_threadlocal thread_local
|
|
#elif __STDC_VERSION__ >= 201112L
|
|
#define zig_threadlocal _Thread_local
|
|
#elif defined(zig_gnuc) || defined(zig_slimcc)
|
|
#define zig_threadlocal __thread
|
|
#elif defined(zig_msvc)
|
|
#define zig_threadlocal __declspec(thread)
|
|
#else
|
|
#define zig_threadlocal zig_threadlocal_unavailable
|
|
#endif
|
|
|
|
#if defined(zig_msvc)
|
|
#define zig_const_arr
|
|
#define zig_callconv(c) __##c
|
|
#else
|
|
#define zig_const_arr static const
|
|
#define zig_callconv(c) __attribute__((c))
|
|
#endif
|
|
|
|
#if zig_has_attribute(naked) || defined(zig_gnuc)
|
|
#define zig_naked_decl __attribute__((naked))
|
|
#define zig_naked __attribute__((naked))
|
|
#elif defined(zig_msvc)
|
|
#define zig_naked_decl
|
|
#define zig_naked __declspec(naked)
|
|
#else
|
|
#define zig_naked_decl zig_naked_unavailable
|
|
#define zig_naked zig_naked_unavailable
|
|
#endif
|
|
|
|
#if zig_has_attribute(cold)
|
|
#define zig_cold __attribute__((cold))
|
|
#else
|
|
#define zig_cold
|
|
#endif
|
|
|
|
#if zig_has_attribute(flatten)
|
|
#define zig_maybe_flatten __attribute__((flatten))
|
|
#else
|
|
#define zig_maybe_flatten
|
|
#endif
|
|
|
|
#if zig_has_attribute(noinline)
|
|
#define zig_never_inline __attribute__((noinline)) zig_maybe_flatten
|
|
#elif defined(zig_msvc)
|
|
#define zig_never_inline __declspec(noinline) zig_maybe_flatten
|
|
#else
|
|
#define zig_never_inline zig_never_inline_unavailable
|
|
#endif
|
|
|
|
#if zig_has_attribute(not_tail_called)
|
|
#define zig_never_tail __attribute__((not_tail_called)) zig_never_inline
|
|
#else
|
|
#define zig_never_tail zig_never_tail_unavailable
|
|
#endif
|
|
|
|
#if zig_has_attribute(musttail)
|
|
#define zig_always_tail __attribute__((musttail))
|
|
#else
|
|
#define zig_always_tail zig_always_tail_unavailable
|
|
#endif
|
|
|
|
#if __STDC_VERSION__ >= 199901L
|
|
#define zig_restrict restrict
|
|
#elif defined(zig_gnuc) || defined(zig_tinyc)
|
|
#define zig_restrict __restrict
|
|
#else
|
|
#define zig_restrict
|
|
#endif
|
|
|
|
#if zig_has_attribute(aligned) || defined(zig_tinyc)
|
|
#define zig_under_align(alignment) __attribute__((aligned(alignment)))
|
|
#elif defined(zig_msvc)
|
|
#define zig_under_align(alignment) __declspec(align(alignment))
|
|
#else
|
|
#define zig_under_align zig_align_unavailable
|
|
#endif
|
|
|
|
#if __STDC_VERSION__ >= 202311L
|
|
#define zig_align(alignment) alignas(alignment)
|
|
#elif __STDC_VERSION__ >= 201112L
|
|
#define zig_align(alignment) _Alignas(alignment)
|
|
#else
|
|
#define zig_align(alignment) zig_under_align(alignment)
|
|
#endif
|
|
|
|
#if zig_has_attribute(aligned) || defined(zig_tinyc)
|
|
#define zig_align_fn(alignment) __attribute__((aligned(alignment)))
|
|
#elif defined(zig_msvc)
|
|
#define zig_align_fn(alignment)
|
|
#else
|
|
#define zig_align_fn zig_align_fn_unavailable
|
|
#endif
|
|
|
|
#if zig_has_attribute(packed) || defined(zig_tinyc)
|
|
#define zig_packed(definition) __attribute__((packed)) definition
|
|
#elif defined(zig_msvc)
|
|
#define zig_packed(definition) __pragma(pack(1)) definition __pragma(pack())
|
|
#else
|
|
#define zig_packed(definition) zig_packed_unavailable
|
|
#endif
|
|
|
|
#if zig_has_attribute(section) || defined(zig_tinyc)
|
|
#define zig_linksection(name) __attribute__((section(name)))
|
|
#define zig_linksection_fn zig_linksection
|
|
#elif defined(zig_msvc)
|
|
#define zig_linksection(name) __pragma(section(name, read, write)) __declspec(allocate(name))
|
|
#define zig_linksection_fn(name) __pragma(section(name, read, execute)) __declspec(code_seg(name))
|
|
#else
|
|
#define zig_linksection(name) zig_linksection_unavailable
|
|
#define zig_linksection_fn zig_linksection
|
|
#endif
|
|
|
|
#if zig_has_builtin(unreachable) || defined(zig_gnuc) || defined(zig_tinyc)
|
|
#define zig_unreachable() __builtin_unreachable()
|
|
#elif defined(zig_msvc)
|
|
#define zig_unreachable() __assume(0)
|
|
#else
|
|
#define zig_unreachable()
|
|
#endif
|
|
|
|
#if defined(__cplusplus)
|
|
#define zig_extern extern "C"
|
|
#else
|
|
#define zig_extern extern
|
|
#endif
|
|
|
|
#if defined(zig_msvc)
|
|
#if defined(zig_x86_64)
|
|
#define zig_mangle_c(symbol) symbol
|
|
#else /* zig_x86_64 */
|
|
#define zig_mangle_c(symbol) "_" symbol
|
|
#endif /* zig_x86_64 */
|
|
#else /* zig_msvc */
|
|
#if defined(zig_macho)
|
|
#define zig_mangle_c(symbol) "_" symbol
|
|
#else /* zig_macho */
|
|
#define zig_mangle_c(symbol) symbol
|
|
#endif /* zig_macho */
|
|
#endif /* zig_msvc */
|
|
|
|
#if (zig_has_attribute(alias) || defined(zig_tinyc)) && !defined(zig_macho)
|
|
#define zig_export(symbol, name) __attribute__((alias(symbol)))
|
|
#elif defined(zig_msvc)
|
|
#define zig_export(symbol, name) ; \
|
|
__pragma(comment(linker, "/alternatename:" zig_mangle_c(name) "=" zig_mangle_c(symbol)))
|
|
#else
|
|
#define zig_export(symbol, name) ; \
|
|
__asm(zig_mangle_c(name) " = " zig_mangle_c(symbol))
|
|
#endif
|
|
|
|
#define zig_mangled_tentative zig_mangled
|
|
#define zig_mangled_final zig_mangled
|
|
#if defined(zig_msvc)
|
|
#define zig_mangled(mangled, unmangled) ; \
|
|
zig_export(#mangled, unmangled)
|
|
#define zig_mangled_export(mangled, unmangled, symbol) \
|
|
zig_export(unmangled, #mangled) \
|
|
zig_export(symbol, unmangled)
|
|
#else /* zig_msvc */
|
|
#define zig_mangled(mangled, unmangled) __asm(zig_mangle_c(unmangled))
|
|
#define zig_mangled_export(mangled, unmangled, symbol) \
|
|
zig_mangled_final(mangled, unmangled) \
|
|
zig_export(symbol, unmangled)
|
|
#endif /* zig_msvc */
|
|
|
|
#if defined(zig_msvc)
|
|
#define zig_import(Type, fn_name, libc_name, sig_args, call_args) zig_extern Type fn_name sig_args;\
|
|
__pragma(comment(linker, "/alternatename:" zig_mangle_c(#fn_name) "=" zig_mangle_c(#libc_name)));
|
|
#define zig_import_builtin(Type, fn_name, libc_name, sig_args, call_args) zig_import(Type, fn_name, sig_args, call_args)
|
|
#else /* zig_msvc */
|
|
#define zig_import(Type, fn_name, libc_name, sig_args, call_args) zig_extern Type fn_name sig_args __asm(zig_mangle_c(#libc_name));
|
|
#define zig_import_builtin(Type, fn_name, libc_name, sig_args, call_args) zig_extern Type libc_name sig_args; \
|
|
static inline Type fn_name sig_args { return libc_name call_args; }
|
|
#endif
|
|
|
|
#define zig_expand_import_0(Type, fn_name, libc_name, sig_args, call_args) zig_import(Type, fn_name, libc_name, sig_args, call_args)
|
|
#define zig_expand_import_1(Type, fn_name, libc_name, sig_args, call_args) zig_import_builtin(Type, fn_name, libc_name, sig_args, call_args)
|
|
|
|
#if zig_has_attribute(weak) || defined(zig_gnuc) || defined(zig_tinyc)
|
|
#define zig_weak_linkage __attribute__((weak))
|
|
#define zig_weak_linkage_fn __attribute__((weak))
|
|
#elif defined(zig_msvc)
|
|
#define zig_weak_linkage __declspec(selectany)
|
|
#define zig_weak_linkage_fn
|
|
#else
|
|
#define zig_weak_linkage zig_weak_linkage_unavailable
|
|
#define zig_weak_linkage_fn zig_weak_linkage_unavailable
|
|
#endif
|
|
|
|
#if defined(zig_gnuc) || defined(zig_tinyc) || defined(zig_slimcc)
|
|
#define zig_gnuc_asm
|
|
#endif
|
|
|
|
#if zig_has_builtin(trap)
|
|
#define zig_trap() __builtin_trap()
|
|
#elif defined(zig_msvc)
|
|
|
|
#if defined(zig_x86)
|
|
#define zig_trap() __ud2()
|
|
#else
|
|
#define zig_trap() __fastfail(7)
|
|
#endif
|
|
|
|
#elif defined(zig_gnuc_asm)
|
|
|
|
#if defined(zig_thumb)
|
|
#define zig_trap() __asm__ volatile("udf #0xfe")
|
|
#elif defined(zig_arm) || defined(zig_aarch64)
|
|
#define zig_trap() __asm__ volatile("udf #0xfdee")
|
|
#elif defined(zig_hexagon)
|
|
#define zig_trap() __asm__ volatile("r27:26 = memd(#0xbadc0fee)")
|
|
#elif defined(zig_loongarch) || defined(zig_powerpc)
|
|
#define zig_trap() __asm__ volatile(".word 0x0")
|
|
#elif defined(zig_mips)
|
|
#define zig_trap() __asm__ volatile(".word 0x3d")
|
|
#elif defined(zig_riscv)
|
|
#define zig_trap() __asm__ volatile("unimp")
|
|
#elif defined(zig_s390x)
|
|
#define zig_trap() __asm__ volatile("j 0x2")
|
|
#elif defined(zig_sparc)
|
|
#define zig_trap() __asm__ volatile("illtrap")
|
|
#elif defined(zig_x86)
|
|
#define zig_trap() __asm__ volatile("ud2")
|
|
#else
|
|
#define zig_trap() zig_trap_unavailable
|
|
#endif
|
|
|
|
#else
|
|
#define zig_trap() zig_trap_unavailable
|
|
#endif
|
|
|
|
#if zig_has_builtin(debugtrap)
|
|
#define zig_breakpoint() __builtin_debugtrap()
|
|
#elif defined(zig_msvc)
|
|
#define zig_breakpoint() __debugbreak()
|
|
#elif defined(zig_gnuc_asm)
|
|
|
|
#if defined(zig_arm)
|
|
#define zig_breakpoint() __asm__ volatile("bkpt #0x0")
|
|
#elif defined(zig_aarch64)
|
|
#define zig_breakpoint() __asm__ volatile("brk #0xf000")
|
|
#elif defined(zig_hexagon)
|
|
#define zig_breakpoint() __asm__ volatile("brkpt")
|
|
#elif defined(zig_loongarch)
|
|
#define zig_breakpoint() __asm__ volatile("break 0x0")
|
|
#elif defined(zig_mips)
|
|
#define zig_breakpoint() __asm__ volatile("break")
|
|
#elif defined(zig_powerpc)
|
|
#define zig_breakpoint() __asm__ volatile("trap")
|
|
#elif defined(zig_riscv)
|
|
#define zig_breakpoint() __asm__ volatile("ebreak")
|
|
#elif defined(zig_s390x)
|
|
#define zig_breakpoint() __asm__ volatile("j 0x6")
|
|
#elif defined(zig_sparc)
|
|
#define zig_breakpoint() __asm__ volatile("ta 0x1")
|
|
#elif defined(zig_x86)
|
|
#define zig_breakpoint() __asm__ volatile("int $0x3")
|
|
#else
|
|
#define zig_breakpoint() zig_breakpoint_unavailable
|
|
#endif
|
|
|
|
#else
|
|
#define zig_breakpoint() zig_breakpoint_unavailable
|
|
#endif
|
|
|
|
#if zig_has_builtin(return_address) || defined(zig_gnuc) || defined(zig_tinyc)
|
|
#define zig_return_address() __builtin_extract_return_addr(__builtin_return_address(0))
|
|
#elif defined(zig_msvc)
|
|
#define zig_return_address() _ReturnAddress()
|
|
#else
|
|
#define zig_return_address() 0
|
|
#endif
|
|
|
|
#if zig_has_builtin(frame_address) || defined(zig_gnuc) || defined(zig_tinyc)
|
|
#define zig_frame_address() __builtin_frame_address(0)
|
|
#elif defined(zig_msvc)
|
|
#define zig_frame_address() _AddressOfReturnAddress()
|
|
#else
|
|
#define zig_frame_address() 0
|
|
#endif
|
|
|
|
#if zig_has_builtin(prefetch) || defined(zig_gnuc)
|
|
#define zig_prefetch(addr, rw, locality) __builtin_prefetch(addr, rw, locality)
|
|
#else
|
|
#define zig_prefetch(addr, rw, locality)
|
|
#endif
|
|
|
|
#if zig_has_builtin(memory_size) && zig_has_builtin(memory_grow)
|
|
#define zig_wasm_memory_size(index) __builtin_wasm_memory_size(index)
|
|
#define zig_wasm_memory_grow(index, delta) __builtin_wasm_memory_grow(index, delta)
|
|
#else
|
|
#define zig_wasm_memory_size(index) zig_unimplemented()
|
|
#define zig_wasm_memory_grow(index, delta) zig_unimplemented()
|
|
#endif
|
|
|
|
#if __STDC_VERSION__ >= 202311L
|
|
#define zig_noreturn [[noreturn]]
|
|
#elif __STDC_VERSION__ >= 201112L
|
|
#define zig_noreturn _Noreturn
|
|
#elif zig_has_attribute(noreturn) || defined(zig_gnuc) || defined(zig_tinyc)
|
|
#define zig_noreturn __attribute__((noreturn))
|
|
#elif defined(zig_msvc)
|
|
#define zig_noreturn __declspec(noreturn)
|
|
#else
|
|
#define zig_noreturn
|
|
#endif
|
|
|
|
#define zig_compiler_rt_abbrev_uint32_t si
|
|
#define zig_compiler_rt_abbrev_int32_t si
|
|
#define zig_compiler_rt_abbrev_uint64_t di
|
|
#define zig_compiler_rt_abbrev_int64_t di
|
|
#define zig_compiler_rt_abbrev_zig_u128 ti
|
|
#define zig_compiler_rt_abbrev_zig_i128 ti
|
|
#define zig_compiler_rt_abbrev_zig_f16 hf
|
|
#define zig_compiler_rt_abbrev_zig_f32 sf
|
|
#define zig_compiler_rt_abbrev_zig_f64 df
|
|
#define zig_compiler_rt_abbrev_zig_f80 xf
|
|
#define zig_compiler_rt_abbrev_zig_f128 tf
|
|
|
|
zig_extern void *memcpy (void *zig_restrict, void const *zig_restrict, size_t);
|
|
zig_extern void *memset (void *, int, size_t);
|
|
|
|
/* ================ Bool and 8/16/32/64-bit Integer Support ================= */
|
|
|
|
#include <limits.h>
|
|
|
|
#define zig_bitSizeOf(T) (CHAR_BIT * sizeof(T))
|
|
|
|
#if __STDC_VERSION__ >= 202311L
|
|
/* bool, true, and false are provided by the language. */
|
|
#elif __STDC_VERSION__ >= 199901L || zig_has_include(<stdbool.h>)
|
|
#include <stdbool.h>
|
|
#else
|
|
typedef char bool;
|
|
#define false 0
|
|
#define true 1
|
|
#endif
|
|
|
|
#if __STDC_VERSION__ >= 199901L || defined(zig_msvc) || zig_has_include(<stdint.h>)
|
|
#include <stdint.h>
|
|
#else
|
|
#if SCHAR_MIN == ~0x7F && SCHAR_MAX == 0x7F && UCHAR_MAX == 0xFF
|
|
typedef unsigned char uint8_t;
|
|
typedef signed char int8_t;
|
|
#define INT8_C(c) c
|
|
#define UINT8_C(c) c##U
|
|
#elif SHRT_MIN == ~0x7F && SHRT_MAX == 0x7F && USHRT_MAX == 0xFF
|
|
typedef unsigned short uint8_t;
|
|
typedef signed short int8_t;
|
|
#define INT8_C(c) c
|
|
#define UINT8_C(c) c##U
|
|
#elif INT_MIN == ~0x7F && INT_MAX == 0x7F && UINT_MAX == 0xFF
|
|
typedef unsigned int uint8_t;
|
|
typedef signed int int8_t;
|
|
#define INT8_C(c) c
|
|
#define UINT8_C(c) c##U
|
|
#elif LONG_MIN == ~0x7F && LONG_MAX == 0x7F && ULONG_MAX == 0xFF
|
|
typedef unsigned long uint8_t;
|
|
typedef signed long int8_t;
|
|
#define INT8_C(c) c##L
|
|
#define UINT8_C(c) c##LU
|
|
#elif LLONG_MIN == ~0x7F && LLONG_MAX == 0x7F && ULLONG_MAX == 0xFF
|
|
typedef unsigned long long uint8_t;
|
|
typedef signed long long int8_t;
|
|
#define INT8_C(c) c##LL
|
|
#define UINT8_C(c) c##LLU
|
|
#endif
|
|
#define INT8_MIN (~INT8_C(0x7F))
|
|
#define INT8_MAX ( INT8_C(0x7F))
|
|
#define UINT8_MAX ( INT8_C(0xFF))
|
|
|
|
#if SCHAR_MIN == ~0x7FFF && SCHAR_MAX == 0x7FFF && UCHAR_MAX == 0xFFFF
|
|
typedef unsigned char uint16_t;
|
|
typedef signed char int16_t;
|
|
#define INT16_C(c) c
|
|
#define UINT16_C(c) c##U
|
|
#elif SHRT_MIN == ~0x7FFF && SHRT_MAX == 0x7FFF && USHRT_MAX == 0xFFFF
|
|
typedef unsigned short uint16_t;
|
|
typedef signed short int16_t;
|
|
#define INT16_C(c) c
|
|
#define UINT16_C(c) c##U
|
|
#elif INT_MIN == ~0x7FFF && INT_MAX == 0x7FFF && UINT_MAX == 0xFFFF
|
|
typedef unsigned int uint16_t;
|
|
typedef signed int int16_t;
|
|
#define INT16_C(c) c
|
|
#define UINT16_C(c) c##U
|
|
#elif LONG_MIN == ~0x7FFF && LONG_MAX == 0x7FFF && ULONG_MAX == 0xFFFF
|
|
typedef unsigned long uint16_t;
|
|
typedef signed long int16_t;
|
|
#define INT16_C(c) c##L
|
|
#define UINT16_C(c) c##LU
|
|
#elif LLONG_MIN == ~0x7FFF && LLONG_MAX == 0x7FFF && ULLONG_MAX == 0xFFFF
|
|
typedef unsigned long long uint16_t;
|
|
typedef signed long long int16_t;
|
|
#define INT16_C(c) c##LL
|
|
#define UINT16_C(c) c##LLU
|
|
#endif
|
|
#define INT16_MIN (~INT16_C(0x7FFF))
|
|
#define INT16_MAX ( INT16_C(0x7FFF))
|
|
#define UINT16_MAX ( INT16_C(0xFFFF))
|
|
|
|
#if SCHAR_MIN == ~0x7FFFFFFF && SCHAR_MAX == 0x7FFFFFFF && UCHAR_MAX == 0xFFFFFFFF
|
|
typedef unsigned char uint32_t;
|
|
typedef signed char int32_t;
|
|
#define INT32_C(c) c
|
|
#define UINT32_C(c) c##U
|
|
#elif SHRT_MIN == ~0x7FFFFFFF && SHRT_MAX == 0x7FFFFFFF && USHRT_MAX == 0xFFFFFFFF
|
|
typedef unsigned short uint32_t;
|
|
typedef signed short int32_t;
|
|
#define INT32_C(c) c
|
|
#define UINT32_C(c) c##U
|
|
#elif INT_MIN == ~0x7FFFFFFF && INT_MAX == 0x7FFFFFFF && UINT_MAX == 0xFFFFFFFF
|
|
typedef unsigned int uint32_t;
|
|
typedef signed int int32_t;
|
|
#define INT32_C(c) c
|
|
#define UINT32_C(c) c##U
|
|
#elif LONG_MIN == ~0x7FFFFFFF && LONG_MAX == 0x7FFFFFFF && ULONG_MAX == 0xFFFFFFFF
|
|
typedef unsigned long uint32_t;
|
|
typedef signed long int32_t;
|
|
#define INT32_C(c) c##L
|
|
#define UINT32_C(c) c##LU
|
|
#elif LLONG_MIN == ~0x7FFFFFFF && LLONG_MAX == 0x7FFFFFFF && ULLONG_MAX == 0xFFFFFFFF
|
|
typedef unsigned long long uint32_t;
|
|
typedef signed long long int32_t;
|
|
#define INT32_C(c) c##LL
|
|
#define UINT32_C(c) c##LLU
|
|
#endif
|
|
#define INT32_MIN (~INT32_C(0x7FFFFFFF))
|
|
#define INT32_MAX ( INT32_C(0x7FFFFFFF))
|
|
#define UINT32_MAX ( INT32_C(0xFFFFFFFF))
|
|
|
|
#if SCHAR_MIN == ~0x7FFFFFFFFFFFFFFF && SCHAR_MAX == 0x7FFFFFFFFFFFFFFF && UCHAR_MAX == 0xFFFFFFFFFFFFFFFF
|
|
typedef unsigned char uint64_t;
|
|
typedef signed char int64_t;
|
|
#define INT64_C(c) c
|
|
#define UINT64_C(c) c##U
|
|
#elif SHRT_MIN == ~0x7FFFFFFFFFFFFFFF && SHRT_MAX == 0x7FFFFFFFFFFFFFFF && USHRT_MAX == 0xFFFFFFFFFFFFFFFF
|
|
typedef unsigned short uint64_t;
|
|
typedef signed short int64_t;
|
|
#define INT64_C(c) c
|
|
#define UINT64_C(c) c##U
|
|
#elif INT_MIN == ~0x7FFFFFFFFFFFFFFF && INT_MAX == 0x7FFFFFFFFFFFFFFF && UINT_MAX == 0xFFFFFFFFFFFFFFFF
|
|
typedef unsigned int uint64_t;
|
|
typedef signed int int64_t;
|
|
#define INT64_C(c) c
|
|
#define UINT64_C(c) c##U
|
|
#elif LONG_MIN == ~0x7FFFFFFFFFFFFFFF && LONG_MAX == 0x7FFFFFFFFFFFFFFF && ULONG_MAX == 0xFFFFFFFFFFFFFFFF
|
|
typedef unsigned long uint64_t;
|
|
typedef signed long int64_t;
|
|
#define INT64_C(c) c##L
|
|
#define UINT64_C(c) c##LU
|
|
#elif LLONG_MIN == ~0x7FFFFFFFFFFFFFFF && LLONG_MAX == 0x7FFFFFFFFFFFFFFF && ULLONG_MAX == 0xFFFFFFFFFFFFFFFF
|
|
typedef unsigned long long uint64_t;
|
|
typedef signed long long int64_t;
|
|
#define INT64_C(c) c##LL
|
|
#define UINT64_C(c) c##LLU
|
|
#endif
|
|
#define INT64_MIN (~INT64_C(0x7FFFFFFFFFFFFFFF))
|
|
#define INT64_MAX ( INT64_C(0x7FFFFFFFFFFFFFFF))
|
|
#define UINT64_MAX ( INT64_C(0xFFFFFFFFFFFFFFFF))
|
|
|
|
typedef size_t uintptr_t;
|
|
typedef ptrdiff_t intptr_t;
|
|
|
|
#endif
|
|
|
|
#define zig_minInt_i8 INT8_MIN
|
|
#define zig_maxInt_i8 INT8_MAX
|
|
#define zig_minInt_u8 UINT8_C(0)
|
|
#define zig_maxInt_u8 UINT8_MAX
|
|
#define zig_minInt_i16 INT16_MIN
|
|
#define zig_maxInt_i16 INT16_MAX
|
|
#define zig_minInt_u16 UINT16_C(0)
|
|
#define zig_maxInt_u16 UINT16_MAX
|
|
#define zig_minInt_i32 INT32_MIN
|
|
#define zig_maxInt_i32 INT32_MAX
|
|
#define zig_minInt_u32 UINT32_C(0)
|
|
#define zig_maxInt_u32 UINT32_MAX
|
|
#define zig_minInt_i64 INT64_MIN
|
|
#define zig_maxInt_i64 INT64_MAX
|
|
#define zig_minInt_u64 UINT64_C(0)
|
|
#define zig_maxInt_u64 UINT64_MAX
|
|
|
|
#define zig_intLimit(s, w, limit, bits) zig_shr_##s##w(zig_##limit##Int_##s##w, w - (bits))
|
|
#define zig_minInt_i(w, bits) zig_intLimit(i, w, min, bits)
|
|
#define zig_maxInt_i(w, bits) zig_intLimit(i, w, max, bits)
|
|
#define zig_minInt_u(w, bits) zig_intLimit(u, w, min, bits)
|
|
#define zig_maxInt_u(w, bits) zig_intLimit(u, w, max, bits)
|
|
|
|
#define zig_operator(Type, RhsType, operation, operator) \
|
|
static inline Type zig_##operation(Type lhs, RhsType rhs) { \
|
|
return lhs operator rhs; \
|
|
}
|
|
#define zig_basic_operator(Type, operation, operator) \
|
|
zig_operator(Type, Type, operation, operator)
|
|
#define zig_shift_operator(Type, operation, operator) \
|
|
zig_operator(Type, uint8_t, operation, operator)
|
|
#define zig_int_helpers(w) \
|
|
zig_basic_operator(uint##w##_t, and_u##w, &) \
|
|
zig_basic_operator( int##w##_t, and_i##w, &) \
|
|
zig_basic_operator(uint##w##_t, or_u##w, |) \
|
|
zig_basic_operator( int##w##_t, or_i##w, |) \
|
|
zig_basic_operator(uint##w##_t, xor_u##w, ^) \
|
|
zig_basic_operator( int##w##_t, xor_i##w, ^) \
|
|
zig_shift_operator(uint##w##_t, shl_u##w, <<) \
|
|
zig_shift_operator( int##w##_t, shl_i##w, <<) \
|
|
zig_shift_operator(uint##w##_t, shr_u##w, >>) \
|
|
\
|
|
static inline int##w##_t zig_shr_i##w(int##w##_t lhs, uint8_t rhs) { \
|
|
int##w##_t sign_mask = lhs < INT##w##_C(0) ? -INT##w##_C(1) : INT##w##_C(0); \
|
|
return ((lhs ^ sign_mask) >> rhs) ^ sign_mask; \
|
|
} \
|
|
\
|
|
static inline uint##w##_t zig_not_u##w(uint##w##_t val, uint8_t bits) { \
|
|
return val ^ zig_maxInt_u(w, bits); \
|
|
} \
|
|
\
|
|
static inline int##w##_t zig_not_i##w(int##w##_t val, uint8_t bits) { \
|
|
(void)bits; \
|
|
return ~val; \
|
|
} \
|
|
\
|
|
static inline uint##w##_t zig_wrap_u##w(uint##w##_t val, uint8_t bits) { \
|
|
return val & zig_maxInt_u(w, bits); \
|
|
} \
|
|
\
|
|
static inline int##w##_t zig_wrap_i##w(int##w##_t val, uint8_t bits) { \
|
|
return (val & UINT##w##_C(1) << (bits - UINT8_C(1))) != 0 \
|
|
? val | zig_minInt_i(w, bits) : val & zig_maxInt_i(w, bits); \
|
|
} \
|
|
\
|
|
static inline uint##w##_t zig_abs_i##w(int##w##_t val) { \
|
|
return (val < 0) ? -(uint##w##_t)val : (uint##w##_t)val; \
|
|
} \
|
|
\
|
|
zig_basic_operator(uint##w##_t, div_floor_u##w, /) \
|
|
\
|
|
static inline int##w##_t zig_div_floor_i##w(int##w##_t lhs, int##w##_t rhs) { \
|
|
return lhs / rhs + (lhs % rhs != INT##w##_C(0) ? zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) : INT##w##_C(0)); \
|
|
} \
|
|
\
|
|
zig_basic_operator(uint##w##_t, mod_u##w, %) \
|
|
\
|
|
static inline int##w##_t zig_mod_i##w(int##w##_t lhs, int##w##_t rhs) { \
|
|
int##w##_t rem = lhs % rhs; \
|
|
return rem + (rem != INT##w##_C(0) ? rhs & zig_shr_i##w(lhs ^ rhs, UINT8_C(w) - UINT8_C(1)) : INT##w##_C(0)); \
|
|
} \
|
|
\
|
|
static inline uint##w##_t zig_shlw_u##w(uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \
|
|
return zig_wrap_u##w(zig_shl_u##w(lhs, rhs), bits); \
|
|
} \
|
|
\
|
|
static inline int##w##_t zig_shlw_i##w(int##w##_t lhs, uint8_t rhs, uint8_t bits) { \
|
|
return zig_wrap_i##w((int##w##_t)zig_shl_u##w((uint##w##_t)lhs, rhs), bits); \
|
|
} \
|
|
\
|
|
static inline uint##w##_t zig_addw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
|
|
return zig_wrap_u##w(lhs + rhs, bits); \
|
|
} \
|
|
\
|
|
static inline int##w##_t zig_addw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
|
|
return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs + (uint##w##_t)rhs), bits); \
|
|
} \
|
|
\
|
|
static inline uint##w##_t zig_subw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
|
|
return zig_wrap_u##w(lhs - rhs, bits); \
|
|
} \
|
|
\
|
|
static inline int##w##_t zig_subw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
|
|
return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs - (uint##w##_t)rhs), bits); \
|
|
} \
|
|
\
|
|
static inline uint##w##_t zig_mulw_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
|
|
return zig_wrap_u##w(lhs * rhs, bits); \
|
|
} \
|
|
\
|
|
static inline int##w##_t zig_mulw_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
|
|
return zig_wrap_i##w((int##w##_t)((uint##w##_t)lhs * (uint##w##_t)rhs), bits); \
|
|
}
|
|
zig_int_helpers(8)
|
|
zig_int_helpers(16)
|
|
zig_int_helpers(32)
|
|
zig_int_helpers(64)
|
|
|
|
static inline bool zig_addo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
|
|
uint32_t full_res;
|
|
bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
|
|
*res = zig_wrap_u32(full_res, bits);
|
|
return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
|
|
#else
|
|
*res = zig_addw_u32(lhs, rhs, bits);
|
|
return *res < lhs;
|
|
#endif
|
|
}
|
|
|
|
zig_extern int32_t __addosi4(int32_t lhs, int32_t rhs, int *overflow);
|
|
static inline bool zig_addo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
|
|
int32_t full_res;
|
|
bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
|
|
#else
|
|
int overflow_int;
|
|
int32_t full_res = __addosi4(lhs, rhs, &overflow_int);
|
|
bool overflow = overflow_int != 0;
|
|
#endif
|
|
*res = zig_wrap_i32(full_res, bits);
|
|
return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
|
|
}
|
|
|
|
static inline bool zig_addo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
|
|
uint64_t full_res;
|
|
bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
|
|
*res = zig_wrap_u64(full_res, bits);
|
|
return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
|
|
#else
|
|
*res = zig_addw_u64(lhs, rhs, bits);
|
|
return *res < lhs;
|
|
#endif
|
|
}
|
|
|
|
zig_extern int64_t __addodi4(int64_t lhs, int64_t rhs, int *overflow);
|
|
static inline bool zig_addo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
|
|
int64_t full_res;
|
|
bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
|
|
#else
|
|
int overflow_int;
|
|
int64_t full_res = __addodi4(lhs, rhs, &overflow_int);
|
|
bool overflow = overflow_int != 0;
|
|
#endif
|
|
*res = zig_wrap_i64(full_res, bits);
|
|
return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
|
|
}
|
|
|
|
static inline bool zig_addo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
|
|
uint8_t full_res;
|
|
bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
|
|
*res = zig_wrap_u8(full_res, bits);
|
|
return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
|
|
#else
|
|
uint32_t full_res;
|
|
bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
|
|
*res = (uint8_t)full_res;
|
|
return overflow;
|
|
#endif
|
|
}
|
|
|
|
static inline bool zig_addo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
|
|
int8_t full_res;
|
|
bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
|
|
*res = zig_wrap_i8(full_res, bits);
|
|
return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
|
|
#else
|
|
int32_t full_res;
|
|
bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
|
|
*res = (int8_t)full_res;
|
|
return overflow;
|
|
#endif
|
|
}
|
|
|
|
static inline bool zig_addo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
|
|
uint16_t full_res;
|
|
bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
|
|
*res = zig_wrap_u16(full_res, bits);
|
|
return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
|
|
#else
|
|
uint32_t full_res;
|
|
bool overflow = zig_addo_u32(&full_res, lhs, rhs, bits);
|
|
*res = (uint16_t)full_res;
|
|
return overflow;
|
|
#endif
|
|
}
|
|
|
|
static inline bool zig_addo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(add_overflow) || defined(zig_gnuc)
|
|
int16_t full_res;
|
|
bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
|
|
*res = zig_wrap_i16(full_res, bits);
|
|
return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
|
|
#else
|
|
int32_t full_res;
|
|
bool overflow = zig_addo_i32(&full_res, lhs, rhs, bits);
|
|
*res = (int16_t)full_res;
|
|
return overflow;
|
|
#endif
|
|
}
|
|
|
|
static inline bool zig_subo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
|
|
uint32_t full_res;
|
|
bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
|
|
*res = zig_wrap_u32(full_res, bits);
|
|
return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
|
|
#else
|
|
*res = zig_subw_u32(lhs, rhs, bits);
|
|
return *res > lhs;
|
|
#endif
|
|
}
|
|
|
|
zig_extern int32_t __subosi4(int32_t lhs, int32_t rhs, int *overflow);
|
|
static inline bool zig_subo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
|
|
int32_t full_res;
|
|
bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
|
|
#else
|
|
int overflow_int;
|
|
int32_t full_res = __subosi4(lhs, rhs, &overflow_int);
|
|
bool overflow = overflow_int != 0;
|
|
#endif
|
|
*res = zig_wrap_i32(full_res, bits);
|
|
return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
|
|
}
|
|
|
|
static inline bool zig_subo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
|
|
uint64_t full_res;
|
|
bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
|
|
*res = zig_wrap_u64(full_res, bits);
|
|
return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
|
|
#else
|
|
*res = zig_subw_u64(lhs, rhs, bits);
|
|
return *res > lhs;
|
|
#endif
|
|
}
|
|
|
|
zig_extern int64_t __subodi4(int64_t lhs, int64_t rhs, int *overflow);
|
|
static inline bool zig_subo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
|
|
int64_t full_res;
|
|
bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
|
|
#else
|
|
int overflow_int;
|
|
int64_t full_res = __subodi4(lhs, rhs, &overflow_int);
|
|
bool overflow = overflow_int != 0;
|
|
#endif
|
|
*res = zig_wrap_i64(full_res, bits);
|
|
return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
|
|
}
|
|
|
|
static inline bool zig_subo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
|
|
uint8_t full_res;
|
|
bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
|
|
*res = zig_wrap_u8(full_res, bits);
|
|
return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
|
|
#else
|
|
uint32_t full_res;
|
|
bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
|
|
*res = (uint8_t)full_res;
|
|
return overflow;
|
|
#endif
|
|
}
|
|
|
|
static inline bool zig_subo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
|
|
int8_t full_res;
|
|
bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
|
|
*res = zig_wrap_i8(full_res, bits);
|
|
return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
|
|
#else
|
|
int32_t full_res;
|
|
bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
|
|
*res = (int8_t)full_res;
|
|
return overflow;
|
|
#endif
|
|
}
|
|
|
|
static inline bool zig_subo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
|
|
uint16_t full_res;
|
|
bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
|
|
*res = zig_wrap_u16(full_res, bits);
|
|
return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
|
|
#else
|
|
uint32_t full_res;
|
|
bool overflow = zig_subo_u32(&full_res, lhs, rhs, bits);
|
|
*res = (uint16_t)full_res;
|
|
return overflow;
|
|
#endif
|
|
}
|
|
|
|
static inline bool zig_subo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(sub_overflow) || defined(zig_gnuc)
|
|
int16_t full_res;
|
|
bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
|
|
*res = zig_wrap_i16(full_res, bits);
|
|
return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
|
|
#else
|
|
int32_t full_res;
|
|
bool overflow = zig_subo_i32(&full_res, lhs, rhs, bits);
|
|
*res = (int16_t)full_res;
|
|
return overflow;
|
|
#endif
|
|
}
|
|
|
|
static inline bool zig_mulo_u32(uint32_t *res, uint32_t lhs, uint32_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
|
|
uint32_t full_res;
|
|
bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
|
|
*res = zig_wrap_u32(full_res, bits);
|
|
return overflow || full_res < zig_minInt_u(32, bits) || full_res > zig_maxInt_u(32, bits);
|
|
#else
|
|
*res = zig_mulw_u32(lhs, rhs, bits);
|
|
return rhs != UINT32_C(0) && lhs > zig_maxInt_u(32, bits) / rhs;
|
|
#endif
|
|
}
|
|
|
|
zig_extern int32_t __mulosi4(int32_t lhs, int32_t rhs, int *overflow);
|
|
static inline bool zig_mulo_i32(int32_t *res, int32_t lhs, int32_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
|
|
int32_t full_res;
|
|
bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
|
|
#else
|
|
int overflow_int;
|
|
int32_t full_res = __mulosi4(lhs, rhs, &overflow_int);
|
|
bool overflow = overflow_int != 0;
|
|
#endif
|
|
*res = zig_wrap_i32(full_res, bits);
|
|
return overflow || full_res < zig_minInt_i(32, bits) || full_res > zig_maxInt_i(32, bits);
|
|
}
|
|
|
|
static inline bool zig_mulo_u64(uint64_t *res, uint64_t lhs, uint64_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
|
|
uint64_t full_res;
|
|
bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
|
|
*res = zig_wrap_u64(full_res, bits);
|
|
return overflow || full_res < zig_minInt_u(64, bits) || full_res > zig_maxInt_u(64, bits);
|
|
#else
|
|
*res = zig_mulw_u64(lhs, rhs, bits);
|
|
return rhs != UINT64_C(0) && lhs > zig_maxInt_u(64, bits) / rhs;
|
|
#endif
|
|
}
|
|
|
|
zig_extern int64_t __mulodi4(int64_t lhs, int64_t rhs, int *overflow);
|
|
static inline bool zig_mulo_i64(int64_t *res, int64_t lhs, int64_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
|
|
int64_t full_res;
|
|
bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
|
|
#else
|
|
int overflow_int;
|
|
int64_t full_res = __mulodi4(lhs, rhs, &overflow_int);
|
|
bool overflow = overflow_int != 0;
|
|
#endif
|
|
*res = zig_wrap_i64(full_res, bits);
|
|
return overflow || full_res < zig_minInt_i(64, bits) || full_res > zig_maxInt_i(64, bits);
|
|
}
|
|
|
|
static inline bool zig_mulo_u8(uint8_t *res, uint8_t lhs, uint8_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
|
|
uint8_t full_res;
|
|
bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
|
|
*res = zig_wrap_u8(full_res, bits);
|
|
return overflow || full_res < zig_minInt_u(8, bits) || full_res > zig_maxInt_u(8, bits);
|
|
#else
|
|
uint32_t full_res;
|
|
bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
|
|
*res = (uint8_t)full_res;
|
|
return overflow;
|
|
#endif
|
|
}
|
|
|
|
static inline bool zig_mulo_i8(int8_t *res, int8_t lhs, int8_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
|
|
int8_t full_res;
|
|
bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
|
|
*res = zig_wrap_i8(full_res, bits);
|
|
return overflow || full_res < zig_minInt_i(8, bits) || full_res > zig_maxInt_i(8, bits);
|
|
#else
|
|
int32_t full_res;
|
|
bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
|
|
*res = (int8_t)full_res;
|
|
return overflow;
|
|
#endif
|
|
}
|
|
|
|
static inline bool zig_mulo_u16(uint16_t *res, uint16_t lhs, uint16_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
|
|
uint16_t full_res;
|
|
bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
|
|
*res = zig_wrap_u16(full_res, bits);
|
|
return overflow || full_res < zig_minInt_u(16, bits) || full_res > zig_maxInt_u(16, bits);
|
|
#else
|
|
uint32_t full_res;
|
|
bool overflow = zig_mulo_u32(&full_res, lhs, rhs, bits);
|
|
*res = (uint16_t)full_res;
|
|
return overflow;
|
|
#endif
|
|
}
|
|
|
|
static inline bool zig_mulo_i16(int16_t *res, int16_t lhs, int16_t rhs, uint8_t bits) {
|
|
#if zig_has_builtin(mul_overflow) || defined(zig_gnuc)
|
|
int16_t full_res;
|
|
bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
|
|
*res = zig_wrap_i16(full_res, bits);
|
|
return overflow || full_res < zig_minInt_i(16, bits) || full_res > zig_maxInt_i(16, bits);
|
|
#else
|
|
int32_t full_res;
|
|
bool overflow = zig_mulo_i32(&full_res, lhs, rhs, bits);
|
|
*res = (int16_t)full_res;
|
|
return overflow;
|
|
#endif
|
|
}
|
|
|
|
#define zig_int_builtins(w) \
|
|
static inline bool zig_shlo_u##w(uint##w##_t *res, uint##w##_t lhs, uint8_t rhs, uint8_t bits) { \
|
|
*res = zig_shlw_u##w(lhs, rhs, bits); \
|
|
return lhs > zig_maxInt_u(w, bits) >> rhs; \
|
|
} \
|
|
\
|
|
static inline bool zig_shlo_i##w(int##w##_t *res, int##w##_t lhs, uint8_t rhs, uint8_t bits) { \
|
|
*res = zig_shlw_i##w(lhs, rhs, bits); \
|
|
int##w##_t mask = (int##w##_t)(UINT##w##_MAX << (bits - rhs - 1)); \
|
|
return (lhs & mask) != INT##w##_C(0) && (lhs & mask) != mask; \
|
|
} \
|
|
\
|
|
static inline uint##w##_t zig_shls_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
|
|
uint##w##_t res; \
|
|
if (rhs >= bits) return lhs != UINT##w##_C(0) ? zig_maxInt_u(w, bits) : lhs; \
|
|
return zig_shlo_u##w(&res, lhs, (uint8_t)rhs, bits) ? zig_maxInt_u(w, bits) : res; \
|
|
} \
|
|
\
|
|
static inline int##w##_t zig_shls_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
|
|
int##w##_t res; \
|
|
if ((uint##w##_t)rhs < (uint##w##_t)bits && !zig_shlo_i##w(&res, lhs, (uint8_t)rhs, bits)) return res; \
|
|
return lhs < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \
|
|
} \
|
|
\
|
|
static inline uint##w##_t zig_adds_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
|
|
uint##w##_t res; \
|
|
return zig_addo_u##w(&res, lhs, rhs, bits) ? zig_maxInt_u(w, bits) : res; \
|
|
} \
|
|
\
|
|
static inline int##w##_t zig_adds_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
|
|
int##w##_t res; \
|
|
if (!zig_addo_i##w(&res, lhs, rhs, bits)) return res; \
|
|
return res >= INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \
|
|
} \
|
|
\
|
|
static inline uint##w##_t zig_subs_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
|
|
uint##w##_t res; \
|
|
return zig_subo_u##w(&res, lhs, rhs, bits) ? zig_minInt_u(w, bits) : res; \
|
|
} \
|
|
\
|
|
static inline int##w##_t zig_subs_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
|
|
int##w##_t res; \
|
|
if (!zig_subo_i##w(&res, lhs, rhs, bits)) return res; \
|
|
return res >= INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \
|
|
} \
|
|
\
|
|
static inline uint##w##_t zig_muls_u##w(uint##w##_t lhs, uint##w##_t rhs, uint8_t bits) { \
|
|
uint##w##_t res; \
|
|
return zig_mulo_u##w(&res, lhs, rhs, bits) ? zig_maxInt_u(w, bits) : res; \
|
|
} \
|
|
\
|
|
static inline int##w##_t zig_muls_i##w(int##w##_t lhs, int##w##_t rhs, uint8_t bits) { \
|
|
int##w##_t res; \
|
|
if (!zig_mulo_i##w(&res, lhs, rhs, bits)) return res; \
|
|
return (lhs ^ rhs) < INT##w##_C(0) ? zig_minInt_i(w, bits) : zig_maxInt_i(w, bits); \
|
|
}
|
|
zig_int_builtins(8)
|
|
zig_int_builtins(16)
|
|
zig_int_builtins(32)
|
|
zig_int_builtins(64)
|
|
|
|
#define zig_builtin8(name, val) __builtin_##name(val)
|
|
typedef unsigned int zig_Builtin8;
|
|
|
|
#define zig_builtin16(name, val) __builtin_##name(val)
|
|
typedef unsigned int zig_Builtin16;
|
|
|
|
#if INT_MIN <= INT32_MIN
|
|
#define zig_builtin32(name, val) __builtin_##name(val)
|
|
typedef unsigned int zig_Builtin32;
|
|
#elif LONG_MIN <= INT32_MIN
|
|
#define zig_builtin32(name, val) __builtin_##name##l(val)
|
|
typedef unsigned long zig_Builtin32;
|
|
#endif
|
|
|
|
#if INT_MIN <= INT64_MIN
|
|
#define zig_builtin64(name, val) __builtin_##name(val)
|
|
typedef unsigned int zig_Builtin64;
|
|
#elif LONG_MIN <= INT64_MIN
|
|
#define zig_builtin64(name, val) __builtin_##name##l(val)
|
|
typedef unsigned long zig_Builtin64;
|
|
#elif LLONG_MIN <= INT64_MIN
|
|
#define zig_builtin64(name, val) __builtin_##name##ll(val)
|
|
typedef unsigned long long zig_Builtin64;
|
|
#endif
|
|
|
|
static inline uint8_t zig_byte_swap_u8(uint8_t val, uint8_t bits) {
|
|
return zig_wrap_u8(val >> (8 - bits), bits);
|
|
}
|
|
|
|
static inline int8_t zig_byte_swap_i8(int8_t val, uint8_t bits) {
|
|
return zig_wrap_i8((int8_t)zig_byte_swap_u8((uint8_t)val, bits), bits);
|
|
}
|
|
|
|
static inline uint16_t zig_byte_swap_u16(uint16_t val, uint8_t bits) {
|
|
uint16_t full_res;
|
|
#if zig_has_builtin(bswap16) || defined(zig_gnuc)
|
|
full_res = __builtin_bswap16(val);
|
|
#else
|
|
full_res = (uint16_t)zig_byte_swap_u8((uint8_t)(val >> 0), 8) << 8 |
|
|
(uint16_t)zig_byte_swap_u8((uint8_t)(val >> 8), 8) >> 0;
|
|
#endif
|
|
return zig_wrap_u16(full_res >> (16 - bits), bits);
|
|
}
|
|
|
|
static inline int16_t zig_byte_swap_i16(int16_t val, uint8_t bits) {
|
|
return zig_wrap_i16((int16_t)zig_byte_swap_u16((uint16_t)val, bits), bits);
|
|
}
|
|
|
|
static inline uint32_t zig_byte_swap_u32(uint32_t val, uint8_t bits) {
|
|
uint32_t full_res;
|
|
#if zig_has_builtin(bswap32) || defined(zig_gnuc)
|
|
full_res = __builtin_bswap32(val);
|
|
#else
|
|
full_res = (uint32_t)zig_byte_swap_u16((uint16_t)(val >> 0), 16) << 16 |
|
|
(uint32_t)zig_byte_swap_u16((uint16_t)(val >> 16), 16) >> 0;
|
|
#endif
|
|
return zig_wrap_u32(full_res >> (32 - bits), bits);
|
|
}
|
|
|
|
static inline int32_t zig_byte_swap_i32(int32_t val, uint8_t bits) {
|
|
return zig_wrap_i32((int32_t)zig_byte_swap_u32((uint32_t)val, bits), bits);
|
|
}
|
|
|
|
static inline uint64_t zig_byte_swap_u64(uint64_t val, uint8_t bits) {
|
|
uint64_t full_res;
|
|
#if zig_has_builtin(bswap64) || defined(zig_gnuc)
|
|
full_res = __builtin_bswap64(val);
|
|
#else
|
|
full_res = (uint64_t)zig_byte_swap_u32((uint32_t)(val >> 0), 32) << 32 |
|
|
(uint64_t)zig_byte_swap_u32((uint32_t)(val >> 32), 32) >> 0;
|
|
#endif
|
|
return zig_wrap_u64(full_res >> (64 - bits), bits);
|
|
}
|
|
|
|
static inline int64_t zig_byte_swap_i64(int64_t val, uint8_t bits) {
|
|
return zig_wrap_i64((int64_t)zig_byte_swap_u64((uint64_t)val, bits), bits);
|
|
}
|
|
|
|
static inline uint8_t zig_bit_reverse_u8(uint8_t val, uint8_t bits) {
|
|
uint8_t full_res;
|
|
#if zig_has_builtin(bitreverse8)
|
|
full_res = __builtin_bitreverse8(val);
|
|
#else
|
|
static uint8_t const lut[0x10] = {
|
|
0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe,
|
|
0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf
|
|
};
|
|
full_res = lut[val >> 0 & 0xF] << 4 | lut[val >> 4 & 0xF] << 0;
|
|
#endif
|
|
return zig_wrap_u8(full_res >> (8 - bits), bits);
|
|
}
|
|
|
|
static inline int8_t zig_bit_reverse_i8(int8_t val, uint8_t bits) {
|
|
return zig_wrap_i8((int8_t)zig_bit_reverse_u8((uint8_t)val, bits), bits);
|
|
}
|
|
|
|
static inline uint16_t zig_bit_reverse_u16(uint16_t val, uint8_t bits) {
|
|
uint16_t full_res;
|
|
#if zig_has_builtin(bitreverse16)
|
|
full_res = __builtin_bitreverse16(val);
|
|
#else
|
|
full_res = (uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 0), 8) << 8 |
|
|
(uint16_t)zig_bit_reverse_u8((uint8_t)(val >> 8), 8) >> 0;
|
|
#endif
|
|
return zig_wrap_u16(full_res >> (16 - bits), bits);
|
|
}
|
|
|
|
static inline int16_t zig_bit_reverse_i16(int16_t val, uint8_t bits) {
|
|
return zig_wrap_i16((int16_t)zig_bit_reverse_u16((uint16_t)val, bits), bits);
|
|
}
|
|
|
|
static inline uint32_t zig_bit_reverse_u32(uint32_t val, uint8_t bits) {
|
|
uint32_t full_res;
|
|
#if zig_has_builtin(bitreverse32)
|
|
full_res = __builtin_bitreverse32(val);
|
|
#else
|
|
full_res = (uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 0), 16) << 16 |
|
|
(uint32_t)zig_bit_reverse_u16((uint16_t)(val >> 16), 16) >> 0;
|
|
#endif
|
|
return zig_wrap_u32(full_res >> (32 - bits), bits);
|
|
}
|
|
|
|
static inline int32_t zig_bit_reverse_i32(int32_t val, uint8_t bits) {
|
|
return zig_wrap_i32((int32_t)zig_bit_reverse_u32((uint32_t)val, bits), bits);
|
|
}
|
|
|
|
static inline uint64_t zig_bit_reverse_u64(uint64_t val, uint8_t bits) {
|
|
uint64_t full_res;
|
|
#if zig_has_builtin(bitreverse64)
|
|
full_res = __builtin_bitreverse64(val);
|
|
#else
|
|
full_res = (uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 0), 32) << 32 |
|
|
(uint64_t)zig_bit_reverse_u32((uint32_t)(val >> 32), 32) >> 0;
|
|
#endif
|
|
return zig_wrap_u64(full_res >> (64 - bits), bits);
|
|
}
|
|
|
|
static inline int64_t zig_bit_reverse_i64(int64_t val, uint8_t bits) {
|
|
return zig_wrap_i64((int64_t)zig_bit_reverse_u64((uint64_t)val, bits), bits);
|
|
}
|
|
|
|
#define zig_builtin_popcount_common(w) \
|
|
static inline uint8_t zig_popcount_i##w(int##w##_t val, uint8_t bits) { \
|
|
return zig_popcount_u##w((uint##w##_t)val, bits); \
|
|
}
|
|
#if zig_has_builtin(popcount) || defined(zig_gnuc) || defined(zig_tinyc)
|
|
#define zig_builtin_popcount(w) \
|
|
static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \
|
|
(void)bits; \
|
|
return zig_builtin##w(popcount, val); \
|
|
} \
|
|
\
|
|
zig_builtin_popcount_common(w)
|
|
#else
|
|
#define zig_builtin_popcount(w) \
|
|
static inline uint8_t zig_popcount_u##w(uint##w##_t val, uint8_t bits) { \
|
|
(void)bits; \
|
|
uint##w##_t temp = val - ((val >> 1) & (UINT##w##_MAX / 3)); \
|
|
temp = (temp & (UINT##w##_MAX / 5)) + ((temp >> 2) & (UINT##w##_MAX / 5)); \
|
|
temp = (temp + (temp >> 4)) & (UINT##w##_MAX / 17); \
|
|
return temp * (UINT##w##_MAX / 255) >> (UINT8_C(w) - UINT8_C(8)); \
|
|
} \
|
|
\
|
|
zig_builtin_popcount_common(w)
|
|
#endif
|
|
zig_builtin_popcount(8)
|
|
zig_builtin_popcount(16)
|
|
zig_builtin_popcount(32)
|
|
zig_builtin_popcount(64)
|
|
|
|
#define zig_builtin_ctz_common(w) \
|
|
static inline uint8_t zig_ctz_i##w(int##w##_t val, uint8_t bits) { \
|
|
return zig_ctz_u##w((uint##w##_t)val, bits); \
|
|
}
|
|
#if zig_has_builtin(ctz) || defined(zig_gnuc) || defined(zig_tinyc)
|
|
#define zig_builtin_ctz(w) \
|
|
static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \
|
|
if (val == 0) return bits; \
|
|
return zig_builtin##w(ctz, val); \
|
|
} \
|
|
\
|
|
zig_builtin_ctz_common(w)
|
|
#else
|
|
#define zig_builtin_ctz(w) \
|
|
static inline uint8_t zig_ctz_u##w(uint##w##_t val, uint8_t bits) { \
|
|
return zig_popcount_u##w(zig_not_u##w(val, bits) & zig_subw_u##w(val, 1, bits), bits); \
|
|
} \
|
|
\
|
|
zig_builtin_ctz_common(w)
|
|
#endif
|
|
zig_builtin_ctz(8)
|
|
zig_builtin_ctz(16)
|
|
zig_builtin_ctz(32)
|
|
zig_builtin_ctz(64)
|
|
|
|
#define zig_builtin_clz_common(w) \
|
|
static inline uint8_t zig_clz_i##w(int##w##_t val, uint8_t bits) { \
|
|
return zig_clz_u##w((uint##w##_t)val, bits); \
|
|
}
|
|
#if zig_has_builtin(clz) || defined(zig_gnuc) || defined(zig_tinyc)
|
|
#define zig_builtin_clz(w) \
|
|
static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \
|
|
if (val == 0) return bits; \
|
|
return zig_builtin##w(clz, val) - (zig_bitSizeOf(zig_Builtin##w) - bits); \
|
|
} \
|
|
\
|
|
zig_builtin_clz_common(w)
|
|
#else
|
|
#define zig_builtin_clz(w) \
|
|
static inline uint8_t zig_clz_u##w(uint##w##_t val, uint8_t bits) { \
|
|
return zig_ctz_u##w(zig_bit_reverse_u##w(val, bits), bits); \
|
|
} \
|
|
\
|
|
zig_builtin_clz_common(w)
|
|
#endif
|
|
zig_builtin_clz(8)
|
|
zig_builtin_clz(16)
|
|
zig_builtin_clz(32)
|
|
zig_builtin_clz(64)
|
|
|
|
/* ======================== 128-bit Integer Support ========================= */
|
|
|
|
#if !defined(zig_has_int128)
|
|
# if defined(__SIZEOF_INT128__)
|
|
# define zig_has_int128 1
|
|
# else
|
|
# define zig_has_int128 0
|
|
# endif
|
|
#endif
|
|
|
|
#if zig_has_int128
|
|
|
|
typedef unsigned __int128 zig_u128;
|
|
typedef signed __int128 zig_i128;
|
|
|
|
#define zig_make_u128(hi, lo) ((zig_u128)(hi)<<64|(lo))
|
|
#define zig_make_i128(hi, lo) ((zig_i128)zig_make_u128(hi, lo))
|
|
#define zig_init_u128(hi, lo) zig_make_u128(hi, lo)
|
|
#define zig_init_i128(hi, lo) zig_make_i128(hi, lo)
|
|
#define zig_hi_u128(val) ((uint64_t)((val) >> 64))
|
|
#define zig_lo_u128(val) ((uint64_t)((val) >> 0))
|
|
#define zig_hi_i128(val) (( int64_t)((val) >> 64))
|
|
#define zig_lo_i128(val) ((uint64_t)((val) >> 0))
|
|
#define zig_bitCast_u128(val) ((zig_u128)(val))
|
|
#define zig_bitCast_i128(val) ((zig_i128)(val))
|
|
#define zig_cmp_int128(Type) \
|
|
static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
|
|
return (lhs > rhs) - (lhs < rhs); \
|
|
}
|
|
#define zig_bit_int128(Type, operation, operator) \
|
|
static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
|
|
return lhs operator rhs; \
|
|
}
|
|
|
|
#else /* zig_has_int128 */
|
|
|
|
#if zig_little_endian
|
|
typedef struct { zig_align(16) uint64_t lo; uint64_t hi; } zig_u128;
|
|
typedef struct { zig_align(16) uint64_t lo; int64_t hi; } zig_i128;
|
|
#else
|
|
typedef struct { zig_align(16) uint64_t hi; uint64_t lo; } zig_u128;
|
|
typedef struct { zig_align(16) int64_t hi; uint64_t lo; } zig_i128;
|
|
#endif
|
|
|
|
#define zig_make_u128(hi, lo) ((zig_u128){ .h##i = (hi), .l##o = (lo) })
|
|
#define zig_make_i128(hi, lo) ((zig_i128){ .h##i = (hi), .l##o = (lo) })
|
|
|
|
#if defined(zig_msvc) /* MSVC doesn't allow struct literals in constant expressions */
|
|
#define zig_init_u128(hi, lo) { .h##i = (hi), .l##o = (lo) }
|
|
#define zig_init_i128(hi, lo) { .h##i = (hi), .l##o = (lo) }
|
|
#else /* But non-MSVC doesn't like the unprotected commas */
|
|
#define zig_init_u128(hi, lo) zig_make_u128(hi, lo)
|
|
#define zig_init_i128(hi, lo) zig_make_i128(hi, lo)
|
|
#endif
|
|
#define zig_hi_u128(val) ((val).hi)
|
|
#define zig_lo_u128(val) ((val).lo)
|
|
#define zig_hi_i128(val) ((val).hi)
|
|
#define zig_lo_i128(val) ((val).lo)
|
|
#define zig_bitCast_u128(val) zig_make_u128((uint64_t)(val).hi, (val).lo)
|
|
#define zig_bitCast_i128(val) zig_make_i128(( int64_t)(val).hi, (val).lo)
|
|
#define zig_cmp_int128(Type) \
|
|
static inline int32_t zig_cmp_##Type(zig_##Type lhs, zig_##Type rhs) { \
|
|
return (lhs.hi == rhs.hi) \
|
|
? (lhs.lo > rhs.lo) - (lhs.lo < rhs.lo) \
|
|
: (lhs.hi > rhs.hi) - (lhs.hi < rhs.hi); \
|
|
}
|
|
#define zig_bit_int128(Type, operation, operator) \
|
|
static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
|
|
return (zig_##Type){ .hi = lhs.hi operator rhs.hi, .lo = lhs.lo operator rhs.lo }; \
|
|
}
|
|
|
|
#endif /* zig_has_int128 */
|
|
|
|
#define zig_minInt_u128 zig_make_u128(zig_minInt_u64, zig_minInt_u64)
|
|
#define zig_maxInt_u128 zig_make_u128(zig_maxInt_u64, zig_maxInt_u64)
|
|
#define zig_minInt_i128 zig_make_i128(zig_minInt_i64, zig_minInt_u64)
|
|
#define zig_maxInt_i128 zig_make_i128(zig_maxInt_i64, zig_maxInt_u64)
|
|
|
|
zig_cmp_int128(u128)
|
|
zig_cmp_int128(i128)
|
|
|
|
zig_bit_int128(u128, and, &)
|
|
zig_bit_int128(i128, and, &)
|
|
|
|
zig_bit_int128(u128, or, |)
|
|
zig_bit_int128(i128, or, |)
|
|
|
|
zig_bit_int128(u128, xor, ^)
|
|
zig_bit_int128(i128, xor, ^)
|
|
|
|
static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs);
|
|
|
|
#if zig_has_int128
|
|
|
|
static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) {
|
|
return val ^ zig_maxInt_u(128, bits);
|
|
}
|
|
|
|
static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) {
|
|
(void)bits;
|
|
return ~val;
|
|
}
|
|
|
|
static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
|
|
return lhs >> rhs;
|
|
}
|
|
|
|
static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
|
|
return lhs << rhs;
|
|
}
|
|
|
|
static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
|
|
zig_i128 sign_mask = lhs < zig_make_i128(0, 0) ? -zig_make_i128(0, 1) : zig_make_i128(0, 0);
|
|
return ((lhs ^ sign_mask) >> rhs) ^ sign_mask;
|
|
}
|
|
|
|
static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {
|
|
return lhs << rhs;
|
|
}
|
|
|
|
static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) {
|
|
return lhs + rhs;
|
|
}
|
|
|
|
static inline zig_i128 zig_add_i128(zig_i128 lhs, zig_i128 rhs) {
|
|
return lhs + rhs;
|
|
}
|
|
|
|
static inline zig_u128 zig_sub_u128(zig_u128 lhs, zig_u128 rhs) {
|
|
return lhs - rhs;
|
|
}
|
|
|
|
static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) {
|
|
return lhs - rhs;
|
|
}
|
|
|
|
static inline zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) {
|
|
return lhs * rhs;
|
|
}
|
|
|
|
static inline zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) {
|
|
return lhs * rhs;
|
|
}
|
|
|
|
static inline zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) {
|
|
return lhs / rhs;
|
|
}
|
|
|
|
static inline zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) {
|
|
return lhs / rhs;
|
|
}
|
|
|
|
static inline zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) {
|
|
return lhs % rhs;
|
|
}
|
|
|
|
static inline zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
|
|
return lhs % rhs;
|
|
}
|
|
|
|
#else /* zig_has_int128 */
|
|
|
|
static inline zig_u128 zig_not_u128(zig_u128 val, uint8_t bits) {
|
|
return (zig_u128){ .hi = zig_not_u64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) };
|
|
}
|
|
|
|
static inline zig_i128 zig_not_i128(zig_i128 val, uint8_t bits) {
|
|
return (zig_i128){ .hi = zig_not_i64(val.hi, bits - UINT8_C(64)), .lo = zig_not_u64(val.lo, UINT8_C(64)) };
|
|
}
|
|
|
|
static inline zig_u128 zig_shr_u128(zig_u128 lhs, uint8_t rhs) {
|
|
if (rhs == UINT8_C(0)) return lhs;
|
|
if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = zig_minInt_u64, .lo = lhs.hi >> (rhs - UINT8_C(64)) };
|
|
return (zig_u128){ .hi = lhs.hi >> rhs, .lo = lhs.hi << (UINT8_C(64) - rhs) | lhs.lo >> rhs };
|
|
}
|
|
|
|
static inline zig_u128 zig_shl_u128(zig_u128 lhs, uint8_t rhs) {
|
|
if (rhs == UINT8_C(0)) return lhs;
|
|
if (rhs >= UINT8_C(64)) return (zig_u128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };
|
|
return (zig_u128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
|
|
}
|
|
|
|
static inline zig_i128 zig_shr_i128(zig_i128 lhs, uint8_t rhs) {
|
|
if (rhs == UINT8_C(0)) return lhs;
|
|
if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = zig_shr_i64(lhs.hi, 63), .lo = zig_shr_i64(lhs.hi, (rhs - UINT8_C(64))) };
|
|
return (zig_i128){ .hi = zig_shr_i64(lhs.hi, rhs), .lo = lhs.lo >> rhs | (uint64_t)lhs.hi << (UINT8_C(64) - rhs) };
|
|
}
|
|
|
|
static inline zig_i128 zig_shl_i128(zig_i128 lhs, uint8_t rhs) {
|
|
if (rhs == UINT8_C(0)) return lhs;
|
|
if (rhs >= UINT8_C(64)) return (zig_i128){ .hi = lhs.lo << (rhs - UINT8_C(64)), .lo = zig_minInt_u64 };
|
|
return (zig_i128){ .hi = lhs.hi << rhs | lhs.lo >> (UINT8_C(64) - rhs), .lo = lhs.lo << rhs };
|
|
}
|
|
|
|
static inline zig_u128 zig_add_u128(zig_u128 lhs, zig_u128 rhs) {
|
|
zig_u128 res;
|
|
res.hi = lhs.hi + rhs.hi + zig_addo_u64(&res.lo, lhs.lo, rhs.lo, 64);
|
|
return res;
|
|
}
|
|
|
|
static inline zig_i128 zig_add_i128(zig_i128 lhs, zig_i128 rhs) {
|
|
zig_i128 res;
|
|
res.hi = lhs.hi + rhs.hi + zig_addo_u64(&res.lo, lhs.lo, rhs.lo, 64);
|
|
return res;
|
|
}
|
|
|
|
static inline zig_u128 zig_sub_u128(zig_u128 lhs, zig_u128 rhs) {
|
|
zig_u128 res;
|
|
res.hi = lhs.hi - rhs.hi - zig_subo_u64(&res.lo, lhs.lo, rhs.lo, 64);
|
|
return res;
|
|
}
|
|
|
|
static inline zig_i128 zig_sub_i128(zig_i128 lhs, zig_i128 rhs) {
|
|
zig_i128 res;
|
|
res.hi = lhs.hi - rhs.hi - zig_subo_u64(&res.lo, lhs.lo, rhs.lo, 64);
|
|
return res;
|
|
}
|
|
|
|
zig_extern zig_i128 __multi3(zig_i128 lhs, zig_i128 rhs);
|
|
static zig_i128 zig_mul_i128(zig_i128 lhs, zig_i128 rhs) {
|
|
return __multi3(lhs, rhs);
|
|
}
|
|
|
|
static zig_u128 zig_mul_u128(zig_u128 lhs, zig_u128 rhs) {
|
|
return zig_bitCast_u128(zig_mul_i128(zig_bitCast_i128(lhs), zig_bitCast_i128(rhs)));
|
|
}
|
|
|
|
zig_extern zig_u128 __udivti3(zig_u128 lhs, zig_u128 rhs);
|
|
static zig_u128 zig_div_trunc_u128(zig_u128 lhs, zig_u128 rhs) {
|
|
return __udivti3(lhs, rhs);
|
|
}
|
|
|
|
zig_extern zig_i128 __divti3(zig_i128 lhs, zig_i128 rhs);
|
|
static zig_i128 zig_div_trunc_i128(zig_i128 lhs, zig_i128 rhs) {
|
|
return __divti3(lhs, rhs);
|
|
}
|
|
|
|
zig_extern zig_u128 __umodti3(zig_u128 lhs, zig_u128 rhs);
|
|
static zig_u128 zig_rem_u128(zig_u128 lhs, zig_u128 rhs) {
|
|
return __umodti3(lhs, rhs);
|
|
}
|
|
|
|
zig_extern zig_i128 __modti3(zig_i128 lhs, zig_i128 rhs);
|
|
static zig_i128 zig_rem_i128(zig_i128 lhs, zig_i128 rhs) {
|
|
return __modti3(lhs, rhs);
|
|
}
|
|
|
|
#endif /* zig_has_int128 */
|
|
|
|
#define zig_div_floor_u128 zig_div_trunc_u128
|
|
|
|
static inline zig_i128 zig_div_floor_i128(zig_i128 lhs, zig_i128 rhs) {
|
|
zig_i128 rem = zig_rem_i128(lhs, rhs);
|
|
int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0)
|
|
? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) : INT64_C(0);
|
|
return zig_add_i128(zig_div_trunc_i128(lhs, rhs), zig_make_i128(mask, (uint64_t)mask));
|
|
}
|
|
|
|
#define zig_mod_u128 zig_rem_u128
|
|
|
|
static inline zig_i128 zig_mod_i128(zig_i128 lhs, zig_i128 rhs) {
|
|
zig_i128 rem = zig_rem_i128(lhs, rhs);
|
|
int64_t mask = zig_or_u64((uint64_t)zig_hi_i128(rem), zig_lo_i128(rem)) != UINT64_C(0)
|
|
? zig_shr_i64(zig_xor_i64(zig_hi_i128(lhs), zig_hi_i128(rhs)), UINT8_C(63)) : INT64_C(0);
|
|
return zig_add_i128(rem, zig_and_i128(rhs, zig_make_i128(mask, (uint64_t)mask)));
|
|
}
|
|
|
|
static inline zig_u128 zig_min_u128(zig_u128 lhs, zig_u128 rhs) {
|
|
return zig_cmp_u128(lhs, rhs) < INT32_C(0) ? lhs : rhs;
|
|
}
|
|
|
|
static inline zig_i128 zig_min_i128(zig_i128 lhs, zig_i128 rhs) {
|
|
return zig_cmp_i128(lhs, rhs) < INT32_C(0) ? lhs : rhs;
|
|
}
|
|
|
|
static inline zig_u128 zig_max_u128(zig_u128 lhs, zig_u128 rhs) {
|
|
return zig_cmp_u128(lhs, rhs) > INT32_C(0) ? lhs : rhs;
|
|
}
|
|
|
|
static inline zig_i128 zig_max_i128(zig_i128 lhs, zig_i128 rhs) {
|
|
return zig_cmp_i128(lhs, rhs) > INT32_C(0) ? lhs : rhs;
|
|
}
|
|
|
|
static inline zig_u128 zig_wrap_u128(zig_u128 val, uint8_t bits) {
|
|
return zig_and_u128(val, zig_maxInt_u(128, bits));
|
|
}
|
|
|
|
static inline zig_i128 zig_wrap_i128(zig_i128 val, uint8_t bits) {
|
|
if (bits > UINT8_C(64)) return zig_make_i128(zig_wrap_i64(zig_hi_i128(val), bits - UINT8_C(64)), zig_lo_i128(val));
|
|
int64_t lo = zig_wrap_i64((int64_t)zig_lo_i128(val), bits);
|
|
return zig_make_i128(zig_shr_i64(lo, 63), (uint64_t)lo);
|
|
}
|
|
|
|
static inline zig_u128 zig_shlw_u128(zig_u128 lhs, uint8_t rhs, uint8_t bits) {
|
|
return zig_wrap_u128(zig_shl_u128(lhs, rhs), bits);
|
|
}
|
|
|
|
static inline zig_i128 zig_shlw_i128(zig_i128 lhs, uint8_t rhs, uint8_t bits) {
|
|
return zig_wrap_i128(zig_bitCast_i128(zig_shl_u128(zig_bitCast_u128(lhs), rhs)), bits);
|
|
}
|
|
|
|
static inline zig_u128 zig_addw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
|
|
return zig_wrap_u128(zig_add_u128(lhs, rhs), bits);
|
|
}
|
|
|
|
static inline zig_i128 zig_addw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
|
|
return zig_wrap_i128(zig_bitCast_i128(zig_add_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits);
|
|
}
|
|
|
|
static inline zig_u128 zig_subw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
|
|
return zig_wrap_u128(zig_sub_u128(lhs, rhs), bits);
|
|
}
|
|
|
|
static inline zig_i128 zig_subw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
|
|
return zig_wrap_i128(zig_bitCast_i128(zig_sub_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits);
|
|
}
|
|
|
|
static inline zig_u128 zig_mulw_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
|
|
return zig_wrap_u128(zig_mul_u128(lhs, rhs), bits);
|
|
}
|
|
|
|
static inline zig_i128 zig_mulw_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
|
|
return zig_wrap_i128(zig_bitCast_i128(zig_mul_u128(zig_bitCast_u128(lhs), zig_bitCast_u128(rhs))), bits);
|
|
}
|
|
|
|
static inline zig_u128 zig_abs_i128(zig_i128 val) {
|
|
zig_i128 tmp = zig_shr_i128(val, 127);
|
|
return zig_bitCast_u128(zig_sub_i128(zig_xor_i128(val, tmp), tmp));
|
|
}
|
|
|
|
#if zig_has_int128
|
|
|
|
static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
|
|
#if zig_has_builtin(add_overflow)
|
|
zig_u128 full_res;
|
|
bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
|
|
*res = zig_wrap_u128(full_res, bits);
|
|
return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
|
|
#else
|
|
*res = zig_addw_u128(lhs, rhs, bits);
|
|
return *res < lhs;
|
|
#endif
|
|
}
|
|
|
|
zig_extern zig_i128 __addoti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
|
|
static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
|
|
#if zig_has_builtin(add_overflow)
|
|
zig_i128 full_res;
|
|
bool overflow = __builtin_add_overflow(lhs, rhs, &full_res);
|
|
#else
|
|
int overflow_int;
|
|
zig_i128 full_res = __addoti4(lhs, rhs, &overflow_int);
|
|
bool overflow = overflow_int != 0;
|
|
#endif
|
|
*res = zig_wrap_i128(full_res, bits);
|
|
return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
|
|
}
|
|
|
|
static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
|
|
#if zig_has_builtin(sub_overflow)
|
|
zig_u128 full_res;
|
|
bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
|
|
*res = zig_wrap_u128(full_res, bits);
|
|
return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
|
|
#else
|
|
*res = zig_subw_u128(lhs, rhs, bits);
|
|
return *res > lhs;
|
|
#endif
|
|
}
|
|
|
|
zig_extern zig_i128 __suboti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
|
|
static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
|
|
#if zig_has_builtin(sub_overflow)
|
|
zig_i128 full_res;
|
|
bool overflow = __builtin_sub_overflow(lhs, rhs, &full_res);
|
|
#else
|
|
int overflow_int;
|
|
zig_i128 full_res = __suboti4(lhs, rhs, &overflow_int);
|
|
bool overflow = overflow_int != 0;
|
|
#endif
|
|
*res = zig_wrap_i128(full_res, bits);
|
|
return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
|
|
}
|
|
|
|
static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
|
|
#if zig_has_builtin(mul_overflow)
|
|
zig_u128 full_res;
|
|
bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
|
|
*res = zig_wrap_u128(full_res, bits);
|
|
return overflow || full_res < zig_minInt_u(128, bits) || full_res > zig_maxInt_u(128, bits);
|
|
#else
|
|
*res = zig_mulw_u128(lhs, rhs, bits);
|
|
return rhs != zig_make_u128(0, 0) && lhs > zig_maxInt_u(128, bits) / rhs;
|
|
#endif
|
|
}
|
|
|
|
zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
|
|
static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
|
|
#if zig_has_builtin(mul_overflow)
|
|
zig_i128 full_res;
|
|
bool overflow = __builtin_mul_overflow(lhs, rhs, &full_res);
|
|
#else
|
|
int overflow_int;
|
|
zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);
|
|
bool overflow = overflow_int != 0;
|
|
#endif
|
|
*res = zig_wrap_i128(full_res, bits);
|
|
return overflow || full_res < zig_minInt_i(128, bits) || full_res > zig_maxInt_i(128, bits);
|
|
}
|
|
|
|
#else /* zig_has_int128 */
|
|
|
|
static inline bool zig_addo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
|
|
uint64_t hi;
|
|
bool overflow = zig_addo_u64(&hi, lhs.hi, rhs.hi, bits - 64);
|
|
return overflow ^ zig_addo_u64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
|
|
}
|
|
|
|
static inline bool zig_addo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
|
|
int64_t hi;
|
|
bool overflow = zig_addo_i64(&hi, lhs.hi, rhs.hi, bits - 64);
|
|
return overflow ^ zig_addo_i64(&res->hi, hi, zig_addo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
|
|
}
|
|
|
|
static inline bool zig_subo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
|
|
uint64_t hi;
|
|
bool overflow = zig_subo_u64(&hi, lhs.hi, rhs.hi, bits - 64);
|
|
return overflow ^ zig_subo_u64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
|
|
}
|
|
|
|
static inline bool zig_subo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
|
|
int64_t hi;
|
|
bool overflow = zig_subo_i64(&hi, lhs.hi, rhs.hi, bits - 64);
|
|
return overflow ^ zig_subo_i64(&res->hi, hi, zig_subo_u64(&res->lo, lhs.lo, rhs.lo, 64), bits - 64);
|
|
}
|
|
|
|
static inline bool zig_mulo_u128(zig_u128 *res, zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
|
|
*res = zig_mulw_u128(lhs, rhs, bits);
|
|
return zig_cmp_u128(*res, zig_make_u128(0, 0)) != INT32_C(0) &&
|
|
zig_cmp_u128(lhs, zig_div_trunc_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0);
|
|
}
|
|
|
|
zig_extern zig_i128 __muloti4(zig_i128 lhs, zig_i128 rhs, int *overflow);
|
|
static inline bool zig_mulo_i128(zig_i128 *res, zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
|
|
int overflow_int;
|
|
zig_i128 full_res = __muloti4(lhs, rhs, &overflow_int);
|
|
bool overflow = overflow_int != 0 ||
|
|
zig_cmp_i128(full_res, zig_minInt_i(128, bits)) < INT32_C(0) ||
|
|
zig_cmp_i128(full_res, zig_maxInt_i(128, bits)) > INT32_C(0);
|
|
*res = zig_wrap_i128(full_res, bits);
|
|
return overflow;
|
|
}
|
|
|
|
#endif /* zig_has_int128 */
|
|
|
|
static inline bool zig_shlo_u128(zig_u128 *res, zig_u128 lhs, uint8_t rhs, uint8_t bits) {
|
|
*res = zig_shlw_u128(lhs, rhs, bits);
|
|
return zig_cmp_u128(lhs, zig_shr_u128(zig_maxInt_u(128, bits), rhs)) > INT32_C(0);
|
|
}
|
|
|
|
static inline bool zig_shlo_i128(zig_i128 *res, zig_i128 lhs, uint8_t rhs, uint8_t bits) {
|
|
*res = zig_shlw_i128(lhs, rhs, bits);
|
|
zig_i128 mask = zig_bitCast_i128(zig_shl_u128(zig_maxInt_u128, bits - rhs - UINT8_C(1)));
|
|
return zig_cmp_i128(zig_and_i128(lhs, mask), zig_make_i128(0, 0)) != INT32_C(0) &&
|
|
zig_cmp_i128(zig_and_i128(lhs, mask), mask) != INT32_C(0);
|
|
}
|
|
|
|
static inline zig_u128 zig_shls_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
|
|
zig_u128 res;
|
|
if (zig_cmp_u128(rhs, zig_make_u128(0, bits)) >= INT32_C(0))
|
|
return zig_cmp_u128(lhs, zig_make_u128(0, 0)) != INT32_C(0) ? zig_maxInt_u(128, bits) : lhs;
|
|
return zig_shlo_u128(&res, lhs, (uint8_t)zig_lo_u128(rhs), bits) ? zig_maxInt_u(128, bits) : res;
|
|
}
|
|
|
|
static inline zig_i128 zig_shls_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
|
|
zig_i128 res;
|
|
if (zig_cmp_u128(zig_bitCast_u128(rhs), zig_make_u128(0, bits)) < INT32_C(0) && !zig_shlo_i128(&res, lhs, (uint8_t)zig_lo_i128(rhs), bits)) return res;
|
|
return zig_cmp_i128(lhs, zig_make_i128(0, 0)) < INT32_C(0) ? zig_minInt_i(128, bits) : zig_maxInt_i(128, bits);
|
|
}
|
|
|
|
static inline zig_u128 zig_adds_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
|
|
zig_u128 res;
|
|
return zig_addo_u128(&res, lhs, rhs, bits) ? zig_maxInt_u(128, bits) : res;
|
|
}
|
|
|
|
static inline zig_i128 zig_adds_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
|
|
zig_i128 res;
|
|
if (!zig_addo_i128(&res, lhs, rhs, bits)) return res;
|
|
return zig_cmp_i128(res, zig_make_i128(0, 0)) >= INT32_C(0) ? zig_minInt_i(128, bits) : zig_maxInt_i(128, bits);
|
|
}
|
|
|
|
static inline zig_u128 zig_subs_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
|
|
zig_u128 res;
|
|
return zig_subo_u128(&res, lhs, rhs, bits) ? zig_minInt_u(128, bits) : res;
|
|
}
|
|
|
|
static inline zig_i128 zig_subs_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
|
|
zig_i128 res;
|
|
if (!zig_subo_i128(&res, lhs, rhs, bits)) return res;
|
|
return zig_cmp_i128(res, zig_make_i128(0, 0)) >= INT32_C(0) ? zig_minInt_i(128, bits) : zig_maxInt_i(128, bits);
|
|
}
|
|
|
|
static inline zig_u128 zig_muls_u128(zig_u128 lhs, zig_u128 rhs, uint8_t bits) {
|
|
zig_u128 res;
|
|
return zig_mulo_u128(&res, lhs, rhs, bits) ? zig_maxInt_u(128, bits) : res;
|
|
}
|
|
|
|
static inline zig_i128 zig_muls_i128(zig_i128 lhs, zig_i128 rhs, uint8_t bits) {
|
|
zig_i128 res;
|
|
if (!zig_mulo_i128(&res, lhs, rhs, bits)) return res;
|
|
return zig_cmp_i128(zig_xor_i128(lhs, rhs), zig_make_i128(0, 0)) < INT32_C(0) ? zig_minInt_i(128, bits) : zig_maxInt_i(128, bits);
|
|
}
|
|
|
|
static inline uint8_t zig_clz_u128(zig_u128 val, uint8_t bits) {
|
|
if (bits <= UINT8_C(64)) return zig_clz_u64(zig_lo_u128(val), bits);
|
|
if (zig_hi_u128(val) != 0) return zig_clz_u64(zig_hi_u128(val), bits - UINT8_C(64));
|
|
return zig_clz_u64(zig_lo_u128(val), UINT8_C(64)) + (bits - UINT8_C(64));
|
|
}
|
|
|
|
static inline uint8_t zig_clz_i128(zig_i128 val, uint8_t bits) {
|
|
return zig_clz_u128(zig_bitCast_u128(val), bits);
|
|
}
|
|
|
|
static inline uint8_t zig_ctz_u128(zig_u128 val, uint8_t bits) {
|
|
if (zig_lo_u128(val) != 0) return zig_ctz_u64(zig_lo_u128(val), UINT8_C(64));
|
|
return zig_ctz_u64(zig_hi_u128(val), bits - UINT8_C(64)) + UINT8_C(64);
|
|
}
|
|
|
|
static inline uint8_t zig_ctz_i128(zig_i128 val, uint8_t bits) {
|
|
return zig_ctz_u128(zig_bitCast_u128(val), bits);
|
|
}
|
|
|
|
static inline uint8_t zig_popcount_u128(zig_u128 val, uint8_t bits) {
|
|
return zig_popcount_u64(zig_hi_u128(val), bits - UINT8_C(64)) +
|
|
zig_popcount_u64(zig_lo_u128(val), UINT8_C(64));
|
|
}
|
|
|
|
static inline uint8_t zig_popcount_i128(zig_i128 val, uint8_t bits) {
|
|
return zig_popcount_u128(zig_bitCast_u128(val), bits);
|
|
}
|
|
|
|
static inline zig_u128 zig_byte_swap_u128(zig_u128 val, uint8_t bits) {
|
|
zig_u128 full_res;
|
|
#if zig_has_builtin(bswap128)
|
|
full_res = __builtin_bswap128(val);
|
|
#else
|
|
full_res = zig_make_u128(zig_byte_swap_u64(zig_lo_u128(val), UINT8_C(64)),
|
|
zig_byte_swap_u64(zig_hi_u128(val), UINT8_C(64)));
|
|
#endif
|
|
return zig_shr_u128(full_res, UINT8_C(128) - bits);
|
|
}
|
|
|
|
static inline zig_i128 zig_byte_swap_i128(zig_i128 val, uint8_t bits) {
|
|
return zig_bitCast_i128(zig_byte_swap_u128(zig_bitCast_u128(val), bits));
|
|
}
|
|
|
|
static inline zig_u128 zig_bit_reverse_u128(zig_u128 val, uint8_t bits) {
|
|
return zig_shr_u128(zig_make_u128(zig_bit_reverse_u64(zig_lo_u128(val), UINT8_C(64)),
|
|
zig_bit_reverse_u64(zig_hi_u128(val), UINT8_C(64))),
|
|
UINT8_C(128) - bits);
|
|
}
|
|
|
|
static inline zig_i128 zig_bit_reverse_i128(zig_i128 val, uint8_t bits) {
|
|
return zig_bitCast_i128(zig_bit_reverse_u128(zig_bitCast_u128(val), bits));
|
|
}
|
|
|
|
/* ========================== Big Integer Support =========================== */
|
|
|
|
static inline uint16_t zig_int_bytes(uint16_t bits) {
|
|
uint16_t bytes = (bits + CHAR_BIT - 1) / CHAR_BIT;
|
|
uint16_t alignment = ZIG_TARGET_MAX_INT_ALIGNMENT;
|
|
while (alignment / 2 >= bytes) alignment /= 2;
|
|
return (bytes + alignment - 1) / alignment * alignment;
|
|
}
|
|
|
|
static inline int32_t zig_cmp_big(const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
|
|
const uint8_t *lhs_bytes = lhs;
|
|
const uint8_t *rhs_bytes = rhs;
|
|
uint16_t byte_offset = 0;
|
|
bool do_signed = is_signed;
|
|
uint16_t remaining_bytes = zig_int_bytes(bits);
|
|
|
|
#if zig_little_endian
|
|
byte_offset = remaining_bytes;
|
|
#endif
|
|
|
|
while (remaining_bytes >= 128 / CHAR_BIT) {
|
|
int32_t limb_cmp;
|
|
|
|
#if zig_little_endian
|
|
byte_offset -= 128 / CHAR_BIT;
|
|
#endif
|
|
|
|
if (do_signed) {
|
|
zig_i128 lhs_limb;
|
|
zig_i128 rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
limb_cmp = zig_cmp_i128(lhs_limb, rhs_limb);
|
|
do_signed = false;
|
|
} else {
|
|
zig_u128 lhs_limb;
|
|
zig_u128 rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
limb_cmp = zig_cmp_u128(lhs_limb, rhs_limb);
|
|
}
|
|
|
|
if (limb_cmp != 0) return limb_cmp;
|
|
remaining_bytes -= 128 / CHAR_BIT;
|
|
|
|
#if zig_big_endian
|
|
byte_offset += 128 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 64 / CHAR_BIT) {
|
|
#if zig_little_endian
|
|
byte_offset -= 64 / CHAR_BIT;
|
|
#endif
|
|
|
|
if (do_signed) {
|
|
int64_t lhs_limb;
|
|
int64_t rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
|
|
do_signed = false;
|
|
} else {
|
|
uint64_t lhs_limb;
|
|
uint64_t rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
|
|
}
|
|
|
|
remaining_bytes -= 64 / CHAR_BIT;
|
|
|
|
#if zig_big_endian
|
|
byte_offset += 64 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 32 / CHAR_BIT) {
|
|
#if zig_little_endian
|
|
byte_offset -= 32 / CHAR_BIT;
|
|
#endif
|
|
|
|
if (do_signed) {
|
|
int32_t lhs_limb;
|
|
int32_t rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
|
|
do_signed = false;
|
|
} else {
|
|
uint32_t lhs_limb;
|
|
uint32_t rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
|
|
}
|
|
|
|
remaining_bytes -= 32 / CHAR_BIT;
|
|
|
|
#if zig_big_endian
|
|
byte_offset += 32 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 16 / CHAR_BIT) {
|
|
#if zig_little_endian
|
|
byte_offset -= 16 / CHAR_BIT;
|
|
#endif
|
|
|
|
if (do_signed) {
|
|
int16_t lhs_limb;
|
|
int16_t rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
|
|
do_signed = false;
|
|
} else {
|
|
uint16_t lhs_limb;
|
|
uint16_t rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
|
|
}
|
|
|
|
remaining_bytes -= 16 / CHAR_BIT;
|
|
|
|
#if zig_big_endian
|
|
byte_offset += 16 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 8 / CHAR_BIT) {
|
|
#if zig_little_endian
|
|
byte_offset -= 8 / CHAR_BIT;
|
|
#endif
|
|
|
|
if (do_signed) {
|
|
int8_t lhs_limb;
|
|
int8_t rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
|
|
do_signed = false;
|
|
} else {
|
|
uint8_t lhs_limb;
|
|
uint8_t rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
if (lhs_limb != rhs_limb) return (lhs_limb > rhs_limb) - (lhs_limb < rhs_limb);
|
|
}
|
|
|
|
remaining_bytes -= 8 / CHAR_BIT;
|
|
|
|
#if zig_big_endian
|
|
byte_offset += 8 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static inline void zig_and_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
|
|
uint8_t *res_bytes = res;
|
|
const uint8_t *lhs_bytes = lhs;
|
|
const uint8_t *rhs_bytes = rhs;
|
|
uint16_t byte_offset = 0;
|
|
uint16_t remaining_bytes = zig_int_bytes(bits);
|
|
(void)is_signed;
|
|
|
|
while (remaining_bytes >= 128 / CHAR_BIT) {
|
|
zig_u128 res_limb;
|
|
zig_u128 lhs_limb;
|
|
zig_u128 rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
res_limb = zig_and_u128(lhs_limb, rhs_limb);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
|
|
remaining_bytes -= 128 / CHAR_BIT;
|
|
byte_offset += 128 / CHAR_BIT;
|
|
}
|
|
|
|
while (remaining_bytes >= 64 / CHAR_BIT) {
|
|
uint64_t res_limb;
|
|
uint64_t lhs_limb;
|
|
uint64_t rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
res_limb = zig_and_u64(lhs_limb, rhs_limb);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
|
|
remaining_bytes -= 64 / CHAR_BIT;
|
|
byte_offset += 64 / CHAR_BIT;
|
|
}
|
|
|
|
while (remaining_bytes >= 32 / CHAR_BIT) {
|
|
uint32_t res_limb;
|
|
uint32_t lhs_limb;
|
|
uint32_t rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
res_limb = zig_and_u32(lhs_limb, rhs_limb);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
|
|
remaining_bytes -= 32 / CHAR_BIT;
|
|
byte_offset += 32 / CHAR_BIT;
|
|
}
|
|
|
|
while (remaining_bytes >= 16 / CHAR_BIT) {
|
|
uint16_t res_limb;
|
|
uint16_t lhs_limb;
|
|
uint16_t rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
res_limb = zig_and_u16(lhs_limb, rhs_limb);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
|
|
remaining_bytes -= 16 / CHAR_BIT;
|
|
byte_offset += 16 / CHAR_BIT;
|
|
}
|
|
|
|
while (remaining_bytes >= 8 / CHAR_BIT) {
|
|
uint8_t res_limb;
|
|
uint8_t lhs_limb;
|
|
uint8_t rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
res_limb = zig_and_u8(lhs_limb, rhs_limb);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
|
|
remaining_bytes -= 8 / CHAR_BIT;
|
|
byte_offset += 8 / CHAR_BIT;
|
|
}
|
|
}
|
|
|
|
static inline void zig_or_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
|
|
uint8_t *res_bytes = res;
|
|
const uint8_t *lhs_bytes = lhs;
|
|
const uint8_t *rhs_bytes = rhs;
|
|
uint16_t byte_offset = 0;
|
|
uint16_t remaining_bytes = zig_int_bytes(bits);
|
|
(void)is_signed;
|
|
|
|
while (remaining_bytes >= 128 / CHAR_BIT) {
|
|
zig_u128 res_limb;
|
|
zig_u128 lhs_limb;
|
|
zig_u128 rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
res_limb = zig_or_u128(lhs_limb, rhs_limb);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
|
|
remaining_bytes -= 128 / CHAR_BIT;
|
|
byte_offset += 128 / CHAR_BIT;
|
|
}
|
|
|
|
while (remaining_bytes >= 64 / CHAR_BIT) {
|
|
uint64_t res_limb;
|
|
uint64_t lhs_limb;
|
|
uint64_t rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
res_limb = zig_or_u64(lhs_limb, rhs_limb);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
|
|
remaining_bytes -= 64 / CHAR_BIT;
|
|
byte_offset += 64 / CHAR_BIT;
|
|
}
|
|
|
|
while (remaining_bytes >= 32 / CHAR_BIT) {
|
|
uint32_t res_limb;
|
|
uint32_t lhs_limb;
|
|
uint32_t rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
res_limb = zig_or_u32(lhs_limb, rhs_limb);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
|
|
remaining_bytes -= 32 / CHAR_BIT;
|
|
byte_offset += 32 / CHAR_BIT;
|
|
}
|
|
|
|
while (remaining_bytes >= 16 / CHAR_BIT) {
|
|
uint16_t res_limb;
|
|
uint16_t lhs_limb;
|
|
uint16_t rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
res_limb = zig_or_u16(lhs_limb, rhs_limb);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
|
|
remaining_bytes -= 16 / CHAR_BIT;
|
|
byte_offset += 16 / CHAR_BIT;
|
|
}
|
|
|
|
while (remaining_bytes >= 8 / CHAR_BIT) {
|
|
uint8_t res_limb;
|
|
uint8_t lhs_limb;
|
|
uint8_t rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
res_limb = zig_or_u8(lhs_limb, rhs_limb);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
|
|
remaining_bytes -= 8 / CHAR_BIT;
|
|
byte_offset += 8 / CHAR_BIT;
|
|
}
|
|
}
|
|
|
|
static inline void zig_xor_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
|
|
uint8_t *res_bytes = res;
|
|
const uint8_t *lhs_bytes = lhs;
|
|
const uint8_t *rhs_bytes = rhs;
|
|
uint16_t byte_offset = 0;
|
|
uint16_t remaining_bytes = zig_int_bytes(bits);
|
|
(void)is_signed;
|
|
|
|
while (remaining_bytes >= 128 / CHAR_BIT) {
|
|
zig_u128 res_limb;
|
|
zig_u128 lhs_limb;
|
|
zig_u128 rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
res_limb = zig_xor_u128(lhs_limb, rhs_limb);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
|
|
remaining_bytes -= 128 / CHAR_BIT;
|
|
byte_offset += 128 / CHAR_BIT;
|
|
}
|
|
|
|
while (remaining_bytes >= 64 / CHAR_BIT) {
|
|
uint64_t res_limb;
|
|
uint64_t lhs_limb;
|
|
uint64_t rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
res_limb = zig_xor_u64(lhs_limb, rhs_limb);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
|
|
remaining_bytes -= 64 / CHAR_BIT;
|
|
byte_offset += 64 / CHAR_BIT;
|
|
}
|
|
|
|
while (remaining_bytes >= 32 / CHAR_BIT) {
|
|
uint32_t res_limb;
|
|
uint32_t lhs_limb;
|
|
uint32_t rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
res_limb = zig_xor_u32(lhs_limb, rhs_limb);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
|
|
remaining_bytes -= 32 / CHAR_BIT;
|
|
byte_offset += 32 / CHAR_BIT;
|
|
}
|
|
|
|
while (remaining_bytes >= 16 / CHAR_BIT) {
|
|
uint16_t res_limb;
|
|
uint16_t lhs_limb;
|
|
uint16_t rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
res_limb = zig_xor_u16(lhs_limb, rhs_limb);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
|
|
remaining_bytes -= 16 / CHAR_BIT;
|
|
byte_offset += 16 / CHAR_BIT;
|
|
}
|
|
|
|
while (remaining_bytes >= 8 / CHAR_BIT) {
|
|
uint8_t res_limb;
|
|
uint8_t lhs_limb;
|
|
uint8_t rhs_limb;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
res_limb = zig_xor_u8(lhs_limb, rhs_limb);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
|
|
remaining_bytes -= 8 / CHAR_BIT;
|
|
byte_offset += 8 / CHAR_BIT;
|
|
}
|
|
}
|
|
|
|
static inline bool zig_addo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
|
|
uint8_t *res_bytes = res;
|
|
const uint8_t *lhs_bytes = lhs;
|
|
const uint8_t *rhs_bytes = rhs;
|
|
uint16_t byte_offset = 0;
|
|
uint16_t remaining_bytes = zig_int_bytes(bits);
|
|
uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits);
|
|
bool overflow = false;
|
|
|
|
#if zig_big_endian
|
|
byte_offset = remaining_bytes;
|
|
#endif
|
|
|
|
while (remaining_bytes >= 128 / CHAR_BIT) {
|
|
uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
|
|
|
|
#if zig_big_endian
|
|
byte_offset -= 128 / CHAR_BIT;
|
|
#endif
|
|
|
|
if (remaining_bytes == 128 / CHAR_BIT && is_signed) {
|
|
zig_i128 res_limb;
|
|
zig_i128 tmp_limb;
|
|
zig_i128 lhs_limb;
|
|
zig_i128 rhs_limb;
|
|
bool limb_overflow;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
limb_overflow = zig_addo_i128(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
|
|
overflow = limb_overflow ^ zig_addo_i128(&res_limb, tmp_limb, zig_make_i128(INT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
} else {
|
|
zig_u128 res_limb;
|
|
zig_u128 tmp_limb;
|
|
zig_u128 lhs_limb;
|
|
zig_u128 rhs_limb;
|
|
bool limb_overflow;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
limb_overflow = zig_addo_u128(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
|
|
overflow = limb_overflow ^ zig_addo_u128(&res_limb, tmp_limb, zig_make_u128(UINT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
}
|
|
|
|
remaining_bytes -= 128 / CHAR_BIT;
|
|
|
|
#if zig_little_endian
|
|
byte_offset += 128 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 64 / CHAR_BIT) {
|
|
uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
|
|
|
|
#if zig_big_endian
|
|
byte_offset -= 64 / CHAR_BIT;
|
|
#endif
|
|
|
|
if (remaining_bytes == 64 / CHAR_BIT && is_signed) {
|
|
int64_t res_limb;
|
|
int64_t tmp_limb;
|
|
int64_t lhs_limb;
|
|
int64_t rhs_limb;
|
|
bool limb_overflow;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
limb_overflow = zig_addo_i64(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
|
|
overflow = limb_overflow ^ zig_addo_i64(&res_limb, tmp_limb, overflow ? INT64_C(1) : INT64_C(0), limb_bits);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
} else {
|
|
uint64_t res_limb;
|
|
uint64_t tmp_limb;
|
|
uint64_t lhs_limb;
|
|
uint64_t rhs_limb;
|
|
bool limb_overflow;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
limb_overflow = zig_addo_u64(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
|
|
overflow = limb_overflow ^ zig_addo_u64(&res_limb, tmp_limb, overflow ? UINT64_C(1) : UINT64_C(0), limb_bits);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
}
|
|
|
|
remaining_bytes -= 64 / CHAR_BIT;
|
|
|
|
#if zig_little_endian
|
|
byte_offset += 64 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 32 / CHAR_BIT) {
|
|
uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
|
|
|
|
#if zig_big_endian
|
|
byte_offset -= 32 / CHAR_BIT;
|
|
#endif
|
|
|
|
if (remaining_bytes == 32 / CHAR_BIT && is_signed) {
|
|
int32_t res_limb;
|
|
int32_t tmp_limb;
|
|
int32_t lhs_limb;
|
|
int32_t rhs_limb;
|
|
bool limb_overflow;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
limb_overflow = zig_addo_i32(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
|
|
overflow = limb_overflow ^ zig_addo_i32(&res_limb, tmp_limb, overflow ? INT32_C(1) : INT32_C(0), limb_bits);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
} else {
|
|
uint32_t res_limb;
|
|
uint32_t tmp_limb;
|
|
uint32_t lhs_limb;
|
|
uint32_t rhs_limb;
|
|
bool limb_overflow;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
limb_overflow = zig_addo_u32(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
|
|
overflow = limb_overflow ^ zig_addo_u32(&res_limb, tmp_limb, overflow ? UINT32_C(1) : UINT32_C(0), limb_bits);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
}
|
|
|
|
remaining_bytes -= 32 / CHAR_BIT;
|
|
|
|
#if zig_little_endian
|
|
byte_offset += 32 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 16 / CHAR_BIT) {
|
|
uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
|
|
|
|
#if zig_big_endian
|
|
byte_offset -= 16 / CHAR_BIT;
|
|
#endif
|
|
|
|
if (remaining_bytes == 16 / CHAR_BIT && is_signed) {
|
|
int16_t res_limb;
|
|
int16_t tmp_limb;
|
|
int16_t lhs_limb;
|
|
int16_t rhs_limb;
|
|
bool limb_overflow;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
limb_overflow = zig_addo_i16(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
|
|
overflow = limb_overflow ^ zig_addo_i16(&res_limb, tmp_limb, overflow ? INT16_C(1) : INT16_C(0), limb_bits);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
} else {
|
|
uint16_t res_limb;
|
|
uint16_t tmp_limb;
|
|
uint16_t lhs_limb;
|
|
uint16_t rhs_limb;
|
|
bool limb_overflow;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
limb_overflow = zig_addo_u16(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
|
|
overflow = limb_overflow ^ zig_addo_u16(&res_limb, tmp_limb, overflow ? UINT16_C(1) : UINT16_C(0), limb_bits);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
}
|
|
|
|
remaining_bytes -= 16 / CHAR_BIT;
|
|
|
|
#if zig_little_endian
|
|
byte_offset += 16 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 8 / CHAR_BIT) {
|
|
uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
|
|
|
|
#if zig_big_endian
|
|
byte_offset -= 8 / CHAR_BIT;
|
|
#endif
|
|
|
|
if (remaining_bytes == 8 / CHAR_BIT && is_signed) {
|
|
int8_t res_limb;
|
|
int8_t tmp_limb;
|
|
int8_t lhs_limb;
|
|
int8_t rhs_limb;
|
|
bool limb_overflow;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
limb_overflow = zig_addo_i8(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
|
|
overflow = limb_overflow ^ zig_addo_i8(&res_limb, tmp_limb, overflow ? INT8_C(1) : INT8_C(0), limb_bits);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
} else {
|
|
uint8_t res_limb;
|
|
uint8_t tmp_limb;
|
|
uint8_t lhs_limb;
|
|
uint8_t rhs_limb;
|
|
bool limb_overflow;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
limb_overflow = zig_addo_u8(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
|
|
overflow = limb_overflow ^ zig_addo_u8(&res_limb, tmp_limb, overflow ? UINT8_C(1) : UINT8_C(0), limb_bits);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
}
|
|
|
|
remaining_bytes -= 8 / CHAR_BIT;
|
|
|
|
#if zig_little_endian
|
|
byte_offset += 8 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
return overflow;
|
|
}
|
|
|
|
static inline bool zig_subo_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
|
|
uint8_t *res_bytes = res;
|
|
const uint8_t *lhs_bytes = lhs;
|
|
const uint8_t *rhs_bytes = rhs;
|
|
uint16_t byte_offset = 0;
|
|
uint16_t remaining_bytes = zig_int_bytes(bits);
|
|
uint8_t top_bits = (uint8_t)(remaining_bytes * 8 - bits);
|
|
bool overflow = false;
|
|
|
|
#if zig_big_endian
|
|
byte_offset = remaining_bytes;
|
|
#endif
|
|
|
|
while (remaining_bytes >= 128 / CHAR_BIT) {
|
|
uint8_t limb_bits = 128 - (remaining_bytes == 128 / CHAR_BIT ? top_bits : 0);
|
|
|
|
#if zig_big_endian
|
|
byte_offset -= 128 / CHAR_BIT;
|
|
#endif
|
|
|
|
if (remaining_bytes == 128 / CHAR_BIT && is_signed) {
|
|
zig_i128 res_limb;
|
|
zig_i128 tmp_limb;
|
|
zig_i128 lhs_limb;
|
|
zig_i128 rhs_limb;
|
|
bool limb_overflow;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
limb_overflow = zig_subo_i128(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
|
|
overflow = limb_overflow ^ zig_subo_i128(&res_limb, tmp_limb, zig_make_i128(INT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
} else {
|
|
zig_u128 res_limb;
|
|
zig_u128 tmp_limb;
|
|
zig_u128 lhs_limb;
|
|
zig_u128 rhs_limb;
|
|
bool limb_overflow;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
limb_overflow = zig_subo_u128(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
|
|
overflow = limb_overflow ^ zig_subo_u128(&res_limb, tmp_limb, zig_make_u128(UINT64_C(0), overflow ? UINT64_C(1) : UINT64_C(0)), limb_bits);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
}
|
|
|
|
remaining_bytes -= 128 / CHAR_BIT;
|
|
|
|
#if zig_little_endian
|
|
byte_offset += 128 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 64 / CHAR_BIT) {
|
|
uint8_t limb_bits = 64 - (remaining_bytes == 64 / CHAR_BIT ? top_bits : 0);
|
|
|
|
#if zig_big_endian
|
|
byte_offset -= 64 / CHAR_BIT;
|
|
#endif
|
|
|
|
if (remaining_bytes == 64 / CHAR_BIT && is_signed) {
|
|
int64_t res_limb;
|
|
int64_t tmp_limb;
|
|
int64_t lhs_limb;
|
|
int64_t rhs_limb;
|
|
bool limb_overflow;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
limb_overflow = zig_subo_i64(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
|
|
overflow = limb_overflow ^ zig_subo_i64(&res_limb, tmp_limb, overflow ? INT64_C(1) : INT64_C(0), limb_bits);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
} else {
|
|
uint64_t res_limb;
|
|
uint64_t tmp_limb;
|
|
uint64_t lhs_limb;
|
|
uint64_t rhs_limb;
|
|
bool limb_overflow;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
limb_overflow = zig_subo_u64(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
|
|
overflow = limb_overflow ^ zig_subo_u64(&res_limb, tmp_limb, overflow ? UINT64_C(1) : UINT64_C(0), limb_bits);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
}
|
|
|
|
remaining_bytes -= 64 / CHAR_BIT;
|
|
|
|
#if zig_little_endian
|
|
byte_offset += 64 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 32 / CHAR_BIT) {
|
|
uint8_t limb_bits = 32 - (remaining_bytes == 32 / CHAR_BIT ? top_bits : 0);
|
|
|
|
#if zig_big_endian
|
|
byte_offset -= 32 / CHAR_BIT;
|
|
#endif
|
|
|
|
if (remaining_bytes == 32 / CHAR_BIT && is_signed) {
|
|
int32_t res_limb;
|
|
int32_t tmp_limb;
|
|
int32_t lhs_limb;
|
|
int32_t rhs_limb;
|
|
bool limb_overflow;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
limb_overflow = zig_subo_i32(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
|
|
overflow = limb_overflow ^ zig_subo_i32(&res_limb, tmp_limb, overflow ? INT32_C(1) : INT32_C(0), limb_bits);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
} else {
|
|
uint32_t res_limb;
|
|
uint32_t tmp_limb;
|
|
uint32_t lhs_limb;
|
|
uint32_t rhs_limb;
|
|
bool limb_overflow;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
limb_overflow = zig_subo_u32(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
|
|
overflow = limb_overflow ^ zig_subo_u32(&res_limb, tmp_limb, overflow ? UINT32_C(1) : UINT32_C(0), limb_bits);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
}
|
|
|
|
remaining_bytes -= 32 / CHAR_BIT;
|
|
|
|
#if zig_little_endian
|
|
byte_offset += 32 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 16 / CHAR_BIT) {
|
|
uint8_t limb_bits = 16 - (remaining_bytes == 16 / CHAR_BIT ? top_bits : 0);
|
|
|
|
#if zig_big_endian
|
|
byte_offset -= 16 / CHAR_BIT;
|
|
#endif
|
|
|
|
if (remaining_bytes == 16 / CHAR_BIT && is_signed) {
|
|
int16_t res_limb;
|
|
int16_t tmp_limb;
|
|
int16_t lhs_limb;
|
|
int16_t rhs_limb;
|
|
bool limb_overflow;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
limb_overflow = zig_subo_i16(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
|
|
overflow = limb_overflow ^ zig_subo_i16(&res_limb, tmp_limb, overflow ? INT16_C(1) : INT16_C(0), limb_bits);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
} else {
|
|
uint16_t res_limb;
|
|
uint16_t tmp_limb;
|
|
uint16_t lhs_limb;
|
|
uint16_t rhs_limb;
|
|
bool limb_overflow;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
limb_overflow = zig_subo_u16(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
|
|
overflow = limb_overflow ^ zig_subo_u16(&res_limb, tmp_limb, overflow ? UINT16_C(1) : UINT16_C(0), limb_bits);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
}
|
|
|
|
remaining_bytes -= 16 / CHAR_BIT;
|
|
|
|
#if zig_little_endian
|
|
byte_offset += 16 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 8 / CHAR_BIT) {
|
|
uint8_t limb_bits = 8 - (remaining_bytes == 8 / CHAR_BIT ? top_bits : 0);
|
|
|
|
#if zig_big_endian
|
|
byte_offset -= 8 / CHAR_BIT;
|
|
#endif
|
|
|
|
if (remaining_bytes == 8 / CHAR_BIT && is_signed) {
|
|
int8_t res_limb;
|
|
int8_t tmp_limb;
|
|
int8_t lhs_limb;
|
|
int8_t rhs_limb;
|
|
bool limb_overflow;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
limb_overflow = zig_subo_i8(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
|
|
overflow = limb_overflow ^ zig_subo_i8(&res_limb, tmp_limb, overflow ? INT8_C(1) : INT8_C(0), limb_bits);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
} else {
|
|
uint8_t res_limb;
|
|
uint8_t tmp_limb;
|
|
uint8_t lhs_limb;
|
|
uint8_t rhs_limb;
|
|
bool limb_overflow;
|
|
|
|
memcpy(&lhs_limb, &lhs_bytes[byte_offset], sizeof(lhs_limb));
|
|
memcpy(&rhs_limb, &rhs_bytes[byte_offset], sizeof(rhs_limb));
|
|
limb_overflow = zig_subo_u8(&tmp_limb, lhs_limb, rhs_limb, limb_bits);
|
|
overflow = limb_overflow ^ zig_subo_u8(&res_limb, tmp_limb, overflow ? UINT8_C(1) : UINT8_C(0), limb_bits);
|
|
memcpy(&res_bytes[byte_offset], &res_limb, sizeof(res_limb));
|
|
}
|
|
|
|
remaining_bytes -= 8 / CHAR_BIT;
|
|
|
|
#if zig_little_endian
|
|
byte_offset += 8 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
return overflow;
|
|
}
|
|
|
|
static inline void zig_addw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
|
|
(void)zig_addo_big(res, lhs, rhs, is_signed, bits);
|
|
}
|
|
|
|
static inline void zig_subw_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
|
|
(void)zig_subo_big(res, lhs, rhs, is_signed, bits);
|
|
}
|
|
|
|
zig_extern void __udivei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits);
|
|
static inline void zig_div_trunc_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
|
|
if (!is_signed) {
|
|
__udivei4(res, lhs, rhs, bits);
|
|
return;
|
|
}
|
|
|
|
zig_trap();
|
|
}
|
|
|
|
static inline void zig_div_floor_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
|
|
if (!is_signed) {
|
|
zig_div_trunc_big(res, lhs, rhs, is_signed, bits);
|
|
return;
|
|
}
|
|
|
|
zig_trap();
|
|
}
|
|
|
|
zig_extern void __umodei4(uint32_t *res, const uint32_t *lhs, const uint32_t *rhs, uintptr_t bits);
|
|
static inline void zig_rem_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
|
|
if (!is_signed) {
|
|
__umodei4(res, lhs, rhs, bits);
|
|
return;
|
|
}
|
|
|
|
zig_trap();
|
|
}
|
|
|
|
static inline void zig_mod_big(void *res, const void *lhs, const void *rhs, bool is_signed, uint16_t bits) {
|
|
if (!is_signed) {
|
|
zig_rem_big(res, lhs, rhs, is_signed, bits);
|
|
return;
|
|
}
|
|
|
|
zig_trap();
|
|
}
|
|
|
|
static inline uint16_t zig_clz_big(const void *val, bool is_signed, uint16_t bits) {
|
|
const uint8_t *val_bytes = val;
|
|
uint16_t byte_offset = 0;
|
|
uint16_t remaining_bytes = zig_int_bytes(bits);
|
|
uint16_t skip_bits = remaining_bytes * 8 - bits;
|
|
uint16_t total_lz = 0;
|
|
uint16_t limb_lz;
|
|
(void)is_signed;
|
|
|
|
#if zig_little_endian
|
|
byte_offset = remaining_bytes;
|
|
#endif
|
|
|
|
while (remaining_bytes >= 128 / CHAR_BIT) {
|
|
#if zig_little_endian
|
|
byte_offset -= 128 / CHAR_BIT;
|
|
#endif
|
|
|
|
{
|
|
zig_u128 val_limb;
|
|
|
|
memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
|
|
limb_lz = zig_clz_u128(val_limb, 128 - skip_bits);
|
|
}
|
|
|
|
total_lz += limb_lz;
|
|
if (limb_lz < 128 - skip_bits) return total_lz;
|
|
skip_bits = 0;
|
|
remaining_bytes -= 128 / CHAR_BIT;
|
|
|
|
#if zig_big_endian
|
|
byte_offset += 128 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 64 / CHAR_BIT) {
|
|
#if zig_little_endian
|
|
byte_offset -= 64 / CHAR_BIT;
|
|
#endif
|
|
|
|
{
|
|
uint64_t val_limb;
|
|
|
|
memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
|
|
limb_lz = zig_clz_u64(val_limb, 64 - skip_bits);
|
|
}
|
|
|
|
total_lz += limb_lz;
|
|
if (limb_lz < 64 - skip_bits) return total_lz;
|
|
skip_bits = 0;
|
|
remaining_bytes -= 64 / CHAR_BIT;
|
|
|
|
#if zig_big_endian
|
|
byte_offset += 64 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 32 / CHAR_BIT) {
|
|
#if zig_little_endian
|
|
byte_offset -= 32 / CHAR_BIT;
|
|
#endif
|
|
|
|
{
|
|
uint32_t val_limb;
|
|
|
|
memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
|
|
limb_lz = zig_clz_u32(val_limb, 32 - skip_bits);
|
|
}
|
|
|
|
total_lz += limb_lz;
|
|
if (limb_lz < 32 - skip_bits) return total_lz;
|
|
skip_bits = 0;
|
|
remaining_bytes -= 32 / CHAR_BIT;
|
|
|
|
#if zig_big_endian
|
|
byte_offset += 32 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 16 / CHAR_BIT) {
|
|
#if zig_little_endian
|
|
byte_offset -= 16 / CHAR_BIT;
|
|
#endif
|
|
|
|
{
|
|
uint16_t val_limb;
|
|
|
|
memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
|
|
limb_lz = zig_clz_u16(val_limb, 16 - skip_bits);
|
|
}
|
|
|
|
total_lz += limb_lz;
|
|
if (limb_lz < 16 - skip_bits) return total_lz;
|
|
skip_bits = 0;
|
|
remaining_bytes -= 16 / CHAR_BIT;
|
|
|
|
#if zig_big_endian
|
|
byte_offset += 16 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 8 / CHAR_BIT) {
|
|
#if zig_little_endian
|
|
byte_offset -= 8 / CHAR_BIT;
|
|
#endif
|
|
|
|
{
|
|
uint8_t val_limb;
|
|
|
|
memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
|
|
limb_lz = zig_clz_u8(val_limb, 8 - skip_bits);
|
|
}
|
|
|
|
total_lz += limb_lz;
|
|
if (limb_lz < 8 - skip_bits) return total_lz;
|
|
skip_bits = 0;
|
|
remaining_bytes -= 8 / CHAR_BIT;
|
|
|
|
#if zig_big_endian
|
|
byte_offset += 8 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
return total_lz;
|
|
}
|
|
|
|
static inline uint16_t zig_ctz_big(const void *val, bool is_signed, uint16_t bits) {
|
|
const uint8_t *val_bytes = val;
|
|
uint16_t byte_offset = 0;
|
|
uint16_t remaining_bytes = zig_int_bytes(bits);
|
|
uint16_t total_tz = 0;
|
|
uint16_t limb_tz;
|
|
(void)is_signed;
|
|
|
|
#if zig_big_endian
|
|
byte_offset = remaining_bytes;
|
|
#endif
|
|
|
|
while (remaining_bytes >= 128 / CHAR_BIT) {
|
|
#if zig_big_endian
|
|
byte_offset -= 128 / CHAR_BIT;
|
|
#endif
|
|
|
|
{
|
|
zig_u128 val_limb;
|
|
|
|
memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
|
|
limb_tz = zig_ctz_u128(val_limb, 128);
|
|
}
|
|
|
|
total_tz += limb_tz;
|
|
if (limb_tz < 128) return total_tz;
|
|
remaining_bytes -= 128 / CHAR_BIT;
|
|
|
|
#if zig_little_endian
|
|
byte_offset += 128 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 64 / CHAR_BIT) {
|
|
#if zig_big_endian
|
|
byte_offset -= 64 / CHAR_BIT;
|
|
#endif
|
|
|
|
{
|
|
uint64_t val_limb;
|
|
|
|
memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
|
|
limb_tz = zig_ctz_u64(val_limb, 64);
|
|
}
|
|
|
|
total_tz += limb_tz;
|
|
if (limb_tz < 64) return total_tz;
|
|
remaining_bytes -= 64 / CHAR_BIT;
|
|
|
|
#if zig_little_endian
|
|
byte_offset += 64 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 32 / CHAR_BIT) {
|
|
#if zig_big_endian
|
|
byte_offset -= 32 / CHAR_BIT;
|
|
#endif
|
|
|
|
{
|
|
uint32_t val_limb;
|
|
|
|
memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
|
|
limb_tz = zig_ctz_u32(val_limb, 32);
|
|
}
|
|
|
|
total_tz += limb_tz;
|
|
if (limb_tz < 32) return total_tz;
|
|
remaining_bytes -= 32 / CHAR_BIT;
|
|
|
|
#if zig_little_endian
|
|
byte_offset += 32 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 16 / CHAR_BIT) {
|
|
#if zig_big_endian
|
|
byte_offset -= 16 / CHAR_BIT;
|
|
#endif
|
|
|
|
{
|
|
uint16_t val_limb;
|
|
|
|
memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
|
|
limb_tz = zig_ctz_u16(val_limb, 16);
|
|
}
|
|
|
|
total_tz += limb_tz;
|
|
if (limb_tz < 16) return total_tz;
|
|
remaining_bytes -= 16 / CHAR_BIT;
|
|
|
|
#if zig_little_endian
|
|
byte_offset += 16 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 8 / CHAR_BIT) {
|
|
#if zig_big_endian
|
|
byte_offset -= 8 / CHAR_BIT;
|
|
#endif
|
|
|
|
{
|
|
uint8_t val_limb;
|
|
|
|
memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
|
|
limb_tz = zig_ctz_u8(val_limb, 8);
|
|
}
|
|
|
|
total_tz += limb_tz;
|
|
if (limb_tz < 8) return total_tz;
|
|
remaining_bytes -= 8 / CHAR_BIT;
|
|
|
|
#if zig_little_endian
|
|
byte_offset += 8 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
return total_tz;
|
|
}
|
|
|
|
static inline uint16_t zig_popcount_big(const void *val, bool is_signed, uint16_t bits) {
|
|
const uint8_t *val_bytes = val;
|
|
uint16_t byte_offset = 0;
|
|
uint16_t remaining_bytes = zig_int_bytes(bits);
|
|
uint16_t total_pc = 0;
|
|
(void)is_signed;
|
|
|
|
#if zig_big_endian
|
|
byte_offset = remaining_bytes;
|
|
#endif
|
|
|
|
while (remaining_bytes >= 128 / CHAR_BIT) {
|
|
#if zig_big_endian
|
|
byte_offset -= 128 / CHAR_BIT;
|
|
#endif
|
|
|
|
{
|
|
zig_u128 val_limb;
|
|
|
|
memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
|
|
total_pc += zig_popcount_u128(val_limb, 128);
|
|
}
|
|
|
|
remaining_bytes -= 128 / CHAR_BIT;
|
|
|
|
#if zig_little_endian
|
|
byte_offset += 128 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 64 / CHAR_BIT) {
|
|
#if zig_big_endian
|
|
byte_offset -= 64 / CHAR_BIT;
|
|
#endif
|
|
|
|
{
|
|
uint64_t val_limb;
|
|
|
|
memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
|
|
total_pc += zig_popcount_u64(val_limb, 64);
|
|
}
|
|
|
|
remaining_bytes -= 64 / CHAR_BIT;
|
|
|
|
#if zig_little_endian
|
|
byte_offset += 64 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 32 / CHAR_BIT) {
|
|
#if zig_big_endian
|
|
byte_offset -= 32 / CHAR_BIT;
|
|
#endif
|
|
|
|
{
|
|
uint32_t val_limb;
|
|
|
|
memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
|
|
total_pc += zig_popcount_u32(val_limb, 32);
|
|
}
|
|
|
|
remaining_bytes -= 32 / CHAR_BIT;
|
|
|
|
#if zig_little_endian
|
|
byte_offset += 32 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 16 / CHAR_BIT) {
|
|
#if zig_big_endian
|
|
byte_offset -= 16 / CHAR_BIT;
|
|
#endif
|
|
|
|
{
|
|
uint16_t val_limb;
|
|
|
|
memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
|
|
total_pc = zig_popcount_u16(val_limb, 16);
|
|
}
|
|
|
|
remaining_bytes -= 16 / CHAR_BIT;
|
|
|
|
#if zig_little_endian
|
|
byte_offset += 16 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
while (remaining_bytes >= 8 / CHAR_BIT) {
|
|
#if zig_big_endian
|
|
byte_offset -= 8 / CHAR_BIT;
|
|
#endif
|
|
|
|
{
|
|
uint8_t val_limb;
|
|
|
|
memcpy(&val_limb, &val_bytes[byte_offset], sizeof(val_limb));
|
|
total_pc = zig_popcount_u8(val_limb, 8);
|
|
}
|
|
|
|
remaining_bytes -= 8 / CHAR_BIT;
|
|
|
|
#if zig_little_endian
|
|
byte_offset += 8 / CHAR_BIT;
|
|
#endif
|
|
}
|
|
|
|
return total_pc;
|
|
}
|
|
|
|
/* ========================= Floating Point Support ========================= */
|
|
|
|
#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
|
|
#define __STDC_WANT_IEC_60559_TYPES_EXT__
|
|
#endif
|
|
|
|
#include <float.h>
|
|
|
|
#if defined(zig_msvc)
|
|
float __cdecl nanf(char const* input);
|
|
double __cdecl nan(char const* input);
|
|
long double __cdecl nanl(char const* input);
|
|
|
|
#define zig_msvc_flt_inf ((double)(1e+300 * 1e+300))
|
|
#define zig_msvc_flt_inff ((float)(1e+300 * 1e+300))
|
|
#define zig_msvc_flt_infl ((long double)(1e+300 * 1e+300))
|
|
#define zig_msvc_flt_nan ((double)(zig_msvc_flt_inf * 0.f))
|
|
#define zig_msvc_flt_nanf ((float)(zig_msvc_flt_inf * 0.f))
|
|
#define zig_msvc_flt_nanl ((long double)(zig_msvc_flt_inf * 0.f))
|
|
#define __builtin_nan(str) nan(str)
|
|
#define __builtin_nanf(str) nanf(str)
|
|
#define __builtin_nanl(str) nanl(str)
|
|
#define __builtin_inf() zig_msvc_flt_inf
|
|
#define __builtin_inff() zig_msvc_flt_inff
|
|
#define __builtin_infl() zig_msvc_flt_infl
|
|
#endif
|
|
|
|
#if (zig_has_builtin(nan) && zig_has_builtin(nans) && zig_has_builtin(inf)) || defined(zig_gnuc)
|
|
#define zig_make_special_f16(sign, name, arg, repr) sign zig_make_f16 (__builtin_##name, )(arg)
|
|
#define zig_make_special_f32(sign, name, arg, repr) sign zig_make_f32 (__builtin_##name, )(arg)
|
|
#define zig_make_special_f64(sign, name, arg, repr) sign zig_make_f64 (__builtin_##name, )(arg)
|
|
#define zig_make_special_f80(sign, name, arg, repr) sign zig_make_f80 (__builtin_##name, )(arg)
|
|
#define zig_make_special_f128(sign, name, arg, repr) sign zig_make_f128(__builtin_##name, )(arg)
|
|
#else
|
|
#define zig_make_special_f16(sign, name, arg, repr) zig_bitCast_f16 (repr)
|
|
#define zig_make_special_f32(sign, name, arg, repr) zig_bitCast_f32 (repr)
|
|
#define zig_make_special_f64(sign, name, arg, repr) zig_bitCast_f64 (repr)
|
|
#define zig_make_special_f80(sign, name, arg, repr) zig_bitCast_f80 (repr)
|
|
#define zig_make_special_f128(sign, name, arg, repr) zig_bitCast_f128(repr)
|
|
#endif
|
|
|
|
#define zig_has_f16 1
|
|
#define zig_libc_name_f16(name) __##name##h
|
|
#define zig_init_special_f16(sign, name, arg, repr) zig_make_special_f16(sign, name, arg, repr)
|
|
#if FLT_MANT_DIG == 11
|
|
typedef float zig_f16;
|
|
#define zig_make_f16(fp, repr) fp##f
|
|
#elif DBL_MANT_DIG == 11
|
|
typedef double zig_f16;
|
|
#define zig_make_f16(fp, repr) fp
|
|
#elif LDBL_MANT_DIG == 11
|
|
typedef long double zig_f16;
|
|
#define zig_make_f16(fp, repr) fp##l
|
|
#elif FLT16_MANT_DIG == 11 && (zig_has_builtin(inff16) || defined(zig_gnuc))
|
|
typedef _Float16 zig_f16;
|
|
#define zig_make_f16(fp, repr) fp##f16
|
|
#elif defined(__SIZEOF_FP16__)
|
|
typedef __fp16 zig_f16;
|
|
#define zig_make_f16(fp, repr) fp##f16
|
|
#else
|
|
#undef zig_has_f16
|
|
#define zig_has_f16 0
|
|
#define zig_repr_f16 u16
|
|
typedef uint16_t zig_f16;
|
|
#define zig_make_f16(fp, repr) repr
|
|
#undef zig_make_special_f16
|
|
#define zig_make_special_f16(sign, name, arg, repr) repr
|
|
#undef zig_init_special_f16
|
|
#define zig_init_special_f16(sign, name, arg, repr) repr
|
|
#endif
|
|
#if defined(zig_darwin) && defined(zig_x86)
|
|
typedef uint16_t zig_compiler_rt_f16;
|
|
#else
|
|
typedef zig_f16 zig_compiler_rt_f16;
|
|
#endif
|
|
|
|
#define zig_has_f32 1
|
|
#define zig_libc_name_f32(name) name##f
|
|
#if defined(zig_msvc)
|
|
#define zig_init_special_f32(sign, name, arg, repr) sign zig_make_f32(zig_msvc_flt_##name, )
|
|
#else
|
|
#define zig_init_special_f32(sign, name, arg, repr) zig_make_special_f32(sign, name, arg, repr)
|
|
#endif
|
|
#if FLT_MANT_DIG == 24
|
|
typedef float zig_f32;
|
|
#define zig_make_f32(fp, repr) fp##f
|
|
#elif DBL_MANT_DIG == 24
|
|
typedef double zig_f32;
|
|
#define zig_make_f32(fp, repr) fp
|
|
#elif LDBL_MANT_DIG == 24
|
|
typedef long double zig_f32;
|
|
#define zig_make_f32(fp, repr) fp##l
|
|
#elif FLT32_MANT_DIG == 24
|
|
typedef _Float32 zig_f32;
|
|
#define zig_make_f32(fp, repr) fp##f32
|
|
#else
|
|
#undef zig_has_f32
|
|
#define zig_has_f32 0
|
|
#define zig_repr_f32 u32
|
|
typedef uint32_t zig_f32;
|
|
#define zig_make_f32(fp, repr) repr
|
|
#undef zig_make_special_f32
|
|
#define zig_make_special_f32(sign, name, arg, repr) repr
|
|
#undef zig_init_special_f32
|
|
#define zig_init_special_f32(sign, name, arg, repr) repr
|
|
#endif
|
|
|
|
#define zig_has_f64 1
|
|
#define zig_libc_name_f64(name) name
|
|
|
|
#if defined(zig_msvc)
|
|
#define zig_init_special_f64(sign, name, arg, repr) sign zig_make_f64(zig_msvc_flt_##name, )
|
|
#else
|
|
#define zig_init_special_f64(sign, name, arg, repr) zig_make_special_f64(sign, name, arg, repr)
|
|
#endif
|
|
#if FLT_MANT_DIG == 53
|
|
typedef float zig_f64;
|
|
#define zig_make_f64(fp, repr) fp##f
|
|
#elif DBL_MANT_DIG == 53
|
|
typedef double zig_f64;
|
|
#define zig_make_f64(fp, repr) fp
|
|
#elif LDBL_MANT_DIG == 53
|
|
typedef long double zig_f64;
|
|
#define zig_make_f64(fp, repr) fp##l
|
|
#elif FLT64_MANT_DIG == 53
|
|
typedef _Float64 zig_f64;
|
|
#define zig_make_f64(fp, repr) fp##f64
|
|
#elif FLT32X_MANT_DIG == 53
|
|
typedef _Float32x zig_f64;
|
|
#define zig_make_f64(fp, repr) fp##f32x
|
|
#else
|
|
#undef zig_has_f64
|
|
#define zig_has_f64 0
|
|
#define zig_repr_f64 u64
|
|
typedef uint64_t zig_f64;
|
|
#define zig_make_f64(fp, repr) repr
|
|
#undef zig_make_special_f64
|
|
#define zig_make_special_f64(sign, name, arg, repr) repr
|
|
#undef zig_init_special_f64
|
|
#define zig_init_special_f64(sign, name, arg, repr) repr
|
|
#endif
|
|
|
|
#define zig_has_f80 1
|
|
#define zig_libc_name_f80(name) __##name##x
|
|
#define zig_init_special_f80(sign, name, arg, repr) zig_make_special_f80(sign, name, arg, repr)
|
|
#if FLT_MANT_DIG == 64
|
|
typedef float zig_f80;
|
|
#define zig_make_f80(fp, repr) fp##f
|
|
#elif DBL_MANT_DIG == 64
|
|
typedef double zig_f80;
|
|
#define zig_make_f80(fp, repr) fp
|
|
#elif LDBL_MANT_DIG == 64
|
|
typedef long double zig_f80;
|
|
#define zig_make_f80(fp, repr) fp##l
|
|
#elif FLT80_MANT_DIG == 64
|
|
typedef _Float80 zig_f80;
|
|
#define zig_make_f80(fp, repr) fp##f80
|
|
#elif FLT64X_MANT_DIG == 64
|
|
typedef _Float64x zig_f80;
|
|
#define zig_make_f80(fp, repr) fp##f64x
|
|
#elif defined(__SIZEOF_FLOAT80__)
|
|
typedef __float80 zig_f80;
|
|
#define zig_make_f80(fp, repr) fp##l
|
|
#else
|
|
#undef zig_has_f80
|
|
#define zig_has_f80 0
|
|
#define zig_repr_f80 u128
|
|
typedef zig_u128 zig_f80;
|
|
#define zig_make_f80(fp, repr) repr
|
|
#undef zig_make_special_f80
|
|
#define zig_make_special_f80(sign, name, arg, repr) repr
|
|
#undef zig_init_special_f80
|
|
#define zig_init_special_f80(sign, name, arg, repr) repr
|
|
#endif
|
|
|
|
#if !defined(zig_clang) && defined(zig_gnuc) && defined(zig_x86)
|
|
#define zig_f128_has_miscompilations 1
|
|
#else
|
|
#define zig_f128_has_miscompilations 0
|
|
#endif
|
|
|
|
#define zig_has_f128 1
|
|
#define zig_libc_name_f128(name) name##q
|
|
#define zig_init_special_f128(sign, name, arg, repr) zig_make_special_f128(sign, name, arg, repr)
|
|
#if !zig_f128_has_miscompilations && FLT_MANT_DIG == 113
|
|
typedef float zig_f128;
|
|
#define zig_make_f128(fp, repr) fp##f
|
|
#elif !zig_f128_has_miscompilations && DBL_MANT_DIG == 113
|
|
typedef double zig_f128;
|
|
#define zig_make_f128(fp, repr) fp
|
|
#elif !zig_f128_has_miscompilations && LDBL_MANT_DIG == 113
|
|
typedef long double zig_f128;
|
|
#define zig_make_f128(fp, repr) fp##l
|
|
#elif !zig_f128_has_miscompilations && FLT128_MANT_DIG == 113
|
|
typedef _Float128 zig_f128;
|
|
#define zig_make_f128(fp, repr) fp##f128
|
|
#elif !zig_f128_has_miscompilations && FLT64X_MANT_DIG == 113
|
|
typedef _Float64x zig_f128;
|
|
#define zig_make_f128(fp, repr) fp##f64x
|
|
#elif !zig_f128_has_miscompilations && defined(__SIZEOF_FLOAT128__)
|
|
typedef __float128 zig_f128;
|
|
#define zig_make_f128(fp, repr) fp##q
|
|
#undef zig_make_special_f128
|
|
#define zig_make_special_f128(sign, name, arg, repr) sign __builtin_##name##f128(arg)
|
|
#else
|
|
#undef zig_has_f128
|
|
#define zig_has_f128 0
|
|
#undef zig_make_special_f128
|
|
#undef zig_init_special_f128
|
|
#if defined(zig_darwin) || defined(zig_aarch64)
|
|
typedef __attribute__((__vector_size__(2 * sizeof(uint64_t)))) uint64_t zig_v2u64;
|
|
zig_basic_operator(zig_v2u64, xor_v2u64, ^)
|
|
#define zig_repr_f128 v2u64
|
|
typedef zig_v2u64 zig_f128;
|
|
#define zig_make_f128_zig_make_u128(hi, lo) (zig_f128){ lo, hi }
|
|
#define zig_make_f128_zig_init_u128 zig_make_f128_zig_make_u128
|
|
#define zig_make_f128(fp, repr) zig_make_f128_##repr
|
|
#define zig_make_special_f128(sign, name, arg, repr) zig_make_f128_##repr
|
|
#define zig_init_special_f128(sign, name, arg, repr) zig_make_f128_##repr
|
|
#else
|
|
#define zig_repr_f128 u128
|
|
typedef zig_u128 zig_f128;
|
|
#define zig_make_f128(fp, repr) repr
|
|
#define zig_make_special_f128(sign, name, arg, repr) repr
|
|
#define zig_init_special_f128(sign, name, arg, repr) repr
|
|
#endif
|
|
#endif
|
|
|
|
#if !defined(zig_msvc) && defined(ZIG_TARGET_ABI_MSVC)
|
|
/* Emulate msvc abi on a gnu compiler */
|
|
typedef zig_f64 zig_c_longdouble;
|
|
#elif defined(zig_msvc) && !defined(ZIG_TARGET_ABI_MSVC)
|
|
/* Emulate gnu abi on an msvc compiler */
|
|
typedef zig_f128 zig_c_longdouble;
|
|
#else
|
|
/* Target and compiler abi match */
|
|
typedef long double zig_c_longdouble;
|
|
#endif
|
|
|
|
#define zig_bitCast_float(Type, ReprType) \
|
|
static inline zig_##Type zig_bitCast_##Type(ReprType repr) { \
|
|
zig_##Type result; \
|
|
memcpy(&result, &repr, sizeof(result)); \
|
|
return result; \
|
|
}
|
|
zig_bitCast_float(f16, uint16_t)
|
|
zig_bitCast_float(f32, uint32_t)
|
|
zig_bitCast_float(f64, uint64_t)
|
|
zig_bitCast_float(f80, zig_u128)
|
|
zig_bitCast_float(f128, zig_u128)
|
|
|
|
#define zig_convert_builtin(ExternResType, ResType, operation, ExternArgType, ArgType, version) \
|
|
zig_extern ExternResType zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
|
|
zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(ExternArgType); \
|
|
static inline ResType zig_expand_concat(zig_expand_concat(zig_##operation, \
|
|
zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType)(ArgType arg) { \
|
|
ResType res; \
|
|
ExternResType extern_res; \
|
|
ExternArgType extern_arg; \
|
|
memcpy(&extern_arg, &arg, sizeof(extern_arg)); \
|
|
extern_res = zig_expand_concat(zig_expand_concat(zig_expand_concat(__##operation, \
|
|
zig_compiler_rt_abbrev_##ArgType), zig_compiler_rt_abbrev_##ResType), version)(extern_arg); \
|
|
memcpy(&res, &extern_res, sizeof(res)); \
|
|
return extern_res; \
|
|
}
|
|
zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f32, zig_f32, 2)
|
|
zig_convert_builtin(zig_compiler_rt_f16, zig_f16, trunc, zig_f64, zig_f64, 2)
|
|
zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f80, zig_f80, 2)
|
|
zig_convert_builtin(zig_f16, zig_f16, trunc, zig_f128, zig_f128, 2)
|
|
zig_convert_builtin(zig_f32, zig_f32, extend, zig_compiler_rt_f16, zig_f16, 2)
|
|
zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f80, zig_f80, 2)
|
|
zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f128, zig_f128, 2)
|
|
zig_convert_builtin(zig_f64, zig_f64, extend, zig_compiler_rt_f16, zig_f16, 2)
|
|
zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f80, zig_f80, 2)
|
|
zig_convert_builtin(zig_f64, zig_f64, trunc, zig_f128, zig_f128, 2)
|
|
zig_convert_builtin(zig_f80, zig_f80, extend, zig_f16, zig_f16, 2)
|
|
zig_convert_builtin(zig_f80, zig_f80, extend, zig_f32, zig_f32, 2)
|
|
zig_convert_builtin(zig_f80, zig_f80, extend, zig_f64, zig_f64, 2)
|
|
zig_convert_builtin(zig_f80, zig_f80, trunc, zig_f128, zig_f128, 2)
|
|
zig_convert_builtin(zig_f128, zig_f128, extend, zig_f16, zig_f16, 2)
|
|
zig_convert_builtin(zig_f128, zig_f128, extend, zig_f32, zig_f32, 2)
|
|
zig_convert_builtin(zig_f128, zig_f128, extend, zig_f64, zig_f64, 2)
|
|
zig_convert_builtin(zig_f128, zig_f128, extend, zig_f80, zig_f80, 2)
|
|
|
|
#ifdef __ARM_EABI__
|
|
|
|
zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_d2f(zig_f64);
|
|
static inline zig_f32 zig_truncdfsf(zig_f64 arg) { return __aeabi_d2f(arg); }
|
|
|
|
zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_f2d(zig_f32);
|
|
static inline zig_f64 zig_extendsfdf(zig_f32 arg) { return __aeabi_f2d(arg); }
|
|
|
|
#else /* __ARM_EABI__ */
|
|
|
|
zig_convert_builtin(zig_f32, zig_f32, trunc, zig_f64, zig_f64, 2)
|
|
zig_convert_builtin(zig_f64, zig_f64, extend, zig_f32, zig_f32, 2)
|
|
|
|
#endif /* __ARM_EABI__ */
|
|
|
|
#define zig_float_negate_builtin_0(w, c, sb) \
|
|
zig_expand_concat(zig_xor_, zig_repr_f##w)(arg, zig_make_f##w(-0x0.0p0, c sb))
|
|
#define zig_float_negate_builtin_1(w, c, sb) -arg
|
|
#define zig_float_negate_builtin(w, c, sb) \
|
|
static inline zig_f##w zig_neg_f##w(zig_f##w arg) { \
|
|
return zig_expand_concat(zig_float_negate_builtin_, zig_has_f##w)(w, c, sb); \
|
|
}
|
|
zig_float_negate_builtin(16, , UINT16_C(1) << 15 )
|
|
zig_float_negate_builtin(32, , UINT32_C(1) << 31 )
|
|
zig_float_negate_builtin(64, , UINT64_C(1) << 63 )
|
|
zig_float_negate_builtin(80, zig_make_u128, (UINT64_C(1) << 15, UINT64_C(0)))
|
|
zig_float_negate_builtin(128, zig_make_u128, (UINT64_C(1) << 63, UINT64_C(0)))
|
|
|
|
#define zig_float_less_builtin_0(Type, operation) \
|
|
zig_extern int32_t zig_expand_concat(zig_expand_concat(__##operation, \
|
|
zig_compiler_rt_abbrev_zig_##Type), 2)(zig_##Type, zig_##Type); \
|
|
static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
|
|
return zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 2)(lhs, rhs); \
|
|
}
|
|
#define zig_float_less_builtin_1(Type, operation) \
|
|
static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
|
|
return (!(lhs <= rhs) - (lhs < rhs)); \
|
|
}
|
|
|
|
#define zig_float_greater_builtin_0(Type, operation) \
|
|
zig_float_less_builtin_0(Type, operation)
|
|
#define zig_float_greater_builtin_1(Type, operation) \
|
|
static inline int32_t zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
|
|
return ((lhs > rhs) - !(lhs >= rhs)); \
|
|
}
|
|
|
|
#define zig_float_binary_builtin_0(Type, operation, operator) \
|
|
zig_extern zig_##Type zig_expand_concat(zig_expand_concat(__##operation, \
|
|
zig_compiler_rt_abbrev_zig_##Type), 3)(zig_##Type, zig_##Type); \
|
|
static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
|
|
return zig_expand_concat(zig_expand_concat(__##operation, zig_compiler_rt_abbrev_zig_##Type), 3)(lhs, rhs); \
|
|
}
|
|
#define zig_float_binary_builtin_1(Type, operation, operator) \
|
|
static inline zig_##Type zig_##operation##_##Type(zig_##Type lhs, zig_##Type rhs) { \
|
|
return lhs operator rhs; \
|
|
}
|
|
|
|
#define zig_common_float_builtins(w) \
|
|
zig_convert_builtin( int64_t, int64_t, fix, zig_f##w, zig_f##w, ) \
|
|
zig_convert_builtin(zig_i128, zig_i128, fix, zig_f##w, zig_f##w, ) \
|
|
zig_convert_builtin(zig_u128, zig_u128, fixuns, zig_f##w, zig_f##w, ) \
|
|
zig_convert_builtin(zig_f##w, zig_f##w, float, int64_t, int64_t, ) \
|
|
zig_convert_builtin(zig_f##w, zig_f##w, float, zig_i128, zig_i128, ) \
|
|
zig_convert_builtin(zig_f##w, zig_f##w, floatun, zig_u128, zig_u128, ) \
|
|
zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, cmp) \
|
|
zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, ne) \
|
|
zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, eq) \
|
|
zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, lt) \
|
|
zig_expand_concat(zig_float_less_builtin_, zig_has_f##w)(f##w, le) \
|
|
zig_expand_concat(zig_float_greater_builtin_, zig_has_f##w)(f##w, gt) \
|
|
zig_expand_concat(zig_float_greater_builtin_, zig_has_f##w)(f##w, ge) \
|
|
zig_expand_concat(zig_float_binary_builtin_, zig_has_f##w)(f##w, add, +) \
|
|
zig_expand_concat(zig_float_binary_builtin_, zig_has_f##w)(f##w, sub, -) \
|
|
zig_expand_concat(zig_float_binary_builtin_, zig_has_f##w)(f##w, mul, *) \
|
|
zig_expand_concat(zig_float_binary_builtin_, zig_has_f##w)(f##w, div, /) \
|
|
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(sqrt)))(zig_f##w, zig_sqrt_f##w, zig_libc_name_f##w(sqrt), (zig_f##w x), (x)) \
|
|
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(sin)))(zig_f##w, zig_sin_f##w, zig_libc_name_f##w(sin), (zig_f##w x), (x)) \
|
|
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(cos)))(zig_f##w, zig_cos_f##w, zig_libc_name_f##w(cos), (zig_f##w x), (x)) \
|
|
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(tan)))(zig_f##w, zig_tan_f##w, zig_libc_name_f##w(tan), (zig_f##w x), (x)) \
|
|
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(exp)))(zig_f##w, zig_exp_f##w, zig_libc_name_f##w(exp), (zig_f##w x), (x)) \
|
|
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(exp2)))(zig_f##w, zig_exp2_f##w, zig_libc_name_f##w(exp2), (zig_f##w x), (x)) \
|
|
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(log)))(zig_f##w, zig_log_f##w, zig_libc_name_f##w(log), (zig_f##w x), (x)) \
|
|
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(log2)))(zig_f##w, zig_log2_f##w, zig_libc_name_f##w(log2), (zig_f##w x), (x)) \
|
|
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(log10)))(zig_f##w, zig_log10_f##w, zig_libc_name_f##w(log10), (zig_f##w x), (x)) \
|
|
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fabs)))(zig_f##w, zig_abs_f##w, zig_libc_name_f##w(fabs), (zig_f##w x), (x)) \
|
|
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(floor)))(zig_f##w, zig_floor_f##w, zig_libc_name_f##w(floor), (zig_f##w x), (x)) \
|
|
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(ceil)))(zig_f##w, zig_ceil_f##w, zig_libc_name_f##w(ceil), (zig_f##w x), (x)) \
|
|
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(round)))(zig_f##w, zig_round_f##w, zig_libc_name_f##w(round), (zig_f##w x), (x)) \
|
|
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(trunc)))(zig_f##w, zig_trunc_f##w, zig_libc_name_f##w(trunc), (zig_f##w x), (x)) \
|
|
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fmod)))(zig_f##w, zig_fmod_f##w, zig_libc_name_f##w(fmod), (zig_f##w x, zig_f##w y), (x, y)) \
|
|
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fmin)))(zig_f##w, zig_min_f##w, zig_libc_name_f##w(fmin), (zig_f##w x, zig_f##w y), (x, y)) \
|
|
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fmax)))(zig_f##w, zig_max_f##w, zig_libc_name_f##w(fmax), (zig_f##w x, zig_f##w y), (x, y)) \
|
|
zig_expand_concat(zig_expand_import_, zig_expand_has_builtin(zig_libc_name_f##w(fma)))(zig_f##w, zig_fma_f##w, zig_libc_name_f##w(fma), (zig_f##w x, zig_f##w y, zig_f##w z), (x, y, z)) \
|
|
\
|
|
static inline zig_f##w zig_div_trunc_f##w(zig_f##w lhs, zig_f##w rhs) { \
|
|
return zig_trunc_f##w(zig_div_f##w(lhs, rhs)); \
|
|
} \
|
|
\
|
|
static inline zig_f##w zig_div_floor_f##w(zig_f##w lhs, zig_f##w rhs) { \
|
|
return zig_floor_f##w(zig_div_f##w(lhs, rhs)); \
|
|
} \
|
|
\
|
|
static inline zig_f##w zig_mod_f##w(zig_f##w lhs, zig_f##w rhs) { \
|
|
return zig_sub_f##w(lhs, zig_mul_f##w(zig_div_floor_f##w(lhs, rhs), rhs)); \
|
|
}
|
|
zig_common_float_builtins(16)
|
|
zig_common_float_builtins(32)
|
|
zig_common_float_builtins(64)
|
|
zig_common_float_builtins(80)
|
|
zig_common_float_builtins(128)
|
|
|
|
#define zig_float_builtins(w) \
|
|
zig_convert_builtin( int32_t, int32_t, fix, zig_f##w, zig_f##w, ) \
|
|
zig_convert_builtin(uint32_t, uint32_t, fixuns, zig_f##w, zig_f##w, ) \
|
|
zig_convert_builtin(uint64_t, uint64_t, fixuns, zig_f##w, zig_f##w, ) \
|
|
zig_convert_builtin(zig_f##w, zig_f##w, float, int32_t, int32_t, ) \
|
|
zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint32_t, uint32_t, ) \
|
|
zig_convert_builtin(zig_f##w, zig_f##w, floatun, uint64_t, uint64_t, )
|
|
zig_float_builtins(16)
|
|
zig_float_builtins(80)
|
|
zig_float_builtins(128)
|
|
|
|
#ifdef __ARM_EABI__
|
|
|
|
zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_f2iz(zig_f32);
|
|
static inline int32_t zig_fixsfsi(zig_f32 arg) { return __aeabi_f2iz(arg); }
|
|
|
|
zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_f2uiz(zig_f32);
|
|
static inline uint32_t zig_fixunssfsi(zig_f32 arg) { return __aeabi_f2uiz(arg); }
|
|
|
|
zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_f2ulz(zig_f32);
|
|
static inline uint64_t zig_fixunssfdi(zig_f32 arg) { return __aeabi_f2ulz(arg); }
|
|
|
|
zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_i2f(int32_t);
|
|
static inline zig_f32 zig_floatsisf(int32_t arg) { return __aeabi_i2f(arg); }
|
|
|
|
zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ui2f(uint32_t);
|
|
static inline zig_f32 zig_floatunsisf(uint32_t arg) { return __aeabi_ui2f(arg); }
|
|
|
|
zig_extern zig_callconv(pcs("aapcs")) zig_f32 __aeabi_ul2f(uint64_t);
|
|
static inline zig_f32 zig_floatundisf(uint64_t arg) { return __aeabi_ul2f(arg); }
|
|
|
|
zig_extern zig_callconv(pcs("aapcs")) int32_t __aeabi_d2iz(zig_f64);
|
|
static inline int32_t zig_fixdfsi(zig_f64 arg) { return __aeabi_d2iz(arg); }
|
|
|
|
zig_extern zig_callconv(pcs("aapcs")) uint32_t __aeabi_d2uiz(zig_f64);
|
|
static inline uint32_t zig_fixunsdfsi(zig_f64 arg) { return __aeabi_d2uiz(arg); }
|
|
|
|
zig_extern zig_callconv(pcs("aapcs")) uint64_t __aeabi_d2ulz(zig_f64);
|
|
static inline uint64_t zig_fixunsdfdi(zig_f64 arg) { return __aeabi_d2ulz(arg); }
|
|
|
|
zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_i2d(int32_t);
|
|
static inline zig_f64 zig_floatsidf(int32_t arg) { return __aeabi_i2d(arg); }
|
|
|
|
zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ui2d(uint32_t);
|
|
static inline zig_f64 zig_floatunsidf(uint32_t arg) { return __aeabi_ui2d(arg); }
|
|
|
|
zig_extern zig_callconv(pcs("aapcs")) zig_f64 __aeabi_ul2d(uint64_t);
|
|
static inline zig_f64 zig_floatundidf(uint64_t arg) { return __aeabi_ul2d(arg); }
|
|
|
|
#else /* __ARM_EABI__ */
|
|
|
|
zig_float_builtins(32)
|
|
zig_float_builtins(64)
|
|
|
|
#endif /* __ARM_EABI__ */
|
|
|
|
/* ============================ Atomics Support ============================= */
|
|
|
|
/* Note that atomics should be implemented as macros because most
|
|
compilers silently discard runtime atomic order information. */
|
|
|
|
/* Define fallback implementations first that can later be undef'd on compilers with builtin support. */
|
|
/* Note that zig_atomicrmw_expected is needed to handle aliasing between res and arg. */
|
|
#define zig_atomicrmw_xchg_float(res, obj, arg, order, Type, ReprType) do { \
|
|
zig_##Type zig_atomicrmw_expected; \
|
|
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
|
while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, arg, order, zig_memory_order_relaxed, Type, ReprType)); \
|
|
res = zig_atomicrmw_expected; \
|
|
} while (0)
|
|
#define zig_atomicrmw_add_float(res, obj, arg, order, Type, ReprType) do { \
|
|
zig_##Type zig_atomicrmw_expected; \
|
|
zig_##Type zig_atomicrmw_desired; \
|
|
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
|
do { \
|
|
zig_atomicrmw_desired = zig_add_##Type(zig_atomicrmw_expected, arg); \
|
|
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
|
res = zig_atomicrmw_expected; \
|
|
} while (0)
|
|
#define zig_atomicrmw_sub_float(res, obj, arg, order, Type, ReprType) do { \
|
|
zig_##Type zig_atomicrmw_expected; \
|
|
zig_##Type zig_atomicrmw_desired; \
|
|
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
|
do { \
|
|
zig_atomicrmw_desired = zig_sub_##Type(zig_atomicrmw_expected, arg); \
|
|
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
|
res = zig_atomicrmw_expected; \
|
|
} while (0)
|
|
#define zig_atomicrmw_min_float(res, obj, arg, order, Type, ReprType) do { \
|
|
zig_##Type zig_atomicrmw_expected; \
|
|
zig_##Type zig_atomicrmw_desired; \
|
|
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
|
do { \
|
|
zig_atomicrmw_desired = zig_min_##Type(zig_atomicrmw_expected, arg); \
|
|
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
|
res = zig_atomicrmw_expected; \
|
|
} while (0)
|
|
#define zig_atomicrmw_max_float(res, obj, arg, order, Type, ReprType) do { \
|
|
zig_##Type zig_atomicrmw_expected; \
|
|
zig_##Type zig_atomicrmw_desired; \
|
|
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
|
do { \
|
|
zig_atomicrmw_desired = zig_max_##Type(zig_atomicrmw_expected, arg); \
|
|
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
|
res = zig_atomicrmw_expected; \
|
|
} while (0)
|
|
|
|
#define zig_atomicrmw_xchg_int128(res, obj, arg, order, Type, ReprType) do { \
|
|
zig_##Type zig_atomicrmw_expected; \
|
|
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
|
while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, arg, order, zig_memory_order_relaxed, Type, ReprType)); \
|
|
res = zig_atomicrmw_expected; \
|
|
} while (0)
|
|
#define zig_atomicrmw_add_int128(res, obj, arg, order, Type, ReprType) do { \
|
|
zig_##Type zig_atomicrmw_expected; \
|
|
zig_##Type zig_atomicrmw_desired; \
|
|
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
|
do { \
|
|
zig_atomicrmw_desired = zig_add_##Type(zig_atomicrmw_expected, arg); \
|
|
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
|
res = zig_atomicrmw_expected; \
|
|
} while (0)
|
|
#define zig_atomicrmw_sub_int128(res, obj, arg, order, Type, ReprType) do { \
|
|
zig_##Type zig_atomicrmw_expected; \
|
|
zig_##Type zig_atomicrmw_desired; \
|
|
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
|
do { \
|
|
zig_atomicrmw_desired = zig_sub_##Type(zig_atomicrmw_expected, arg); \
|
|
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
|
res = zig_atomicrmw_expected; \
|
|
} while (0)
|
|
#define zig_atomicrmw_and_int128(res, obj, arg, order, Type, ReprType) do { \
|
|
zig_##Type zig_atomicrmw_expected; \
|
|
zig_##Type zig_atomicrmw_desired; \
|
|
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
|
do { \
|
|
zig_atomicrmw_desired = zig_and_##Type(zig_atomicrmw_expected, arg); \
|
|
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
|
res = zig_atomicrmw_expected; \
|
|
} while (0)
|
|
#define zig_atomicrmw_nand_int128(res, obj, arg, order, Type, ReprType) do { \
|
|
zig_##Type zig_atomicrmw_expected; \
|
|
zig_##Type zig_atomicrmw_desired; \
|
|
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
|
do { \
|
|
zig_atomicrmw_desired = zig_not_##Type(zig_and_##Type(zig_atomicrmw_expected, arg), 128); \
|
|
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
|
res = zig_atomicrmw_expected; \
|
|
} while (0)
|
|
#define zig_atomicrmw_or_int128(res, obj, arg, order, Type, ReprType) do { \
|
|
zig_##Type zig_atomicrmw_expected; \
|
|
zig_##Type zig_atomicrmw_desired; \
|
|
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
|
do { \
|
|
zig_atomicrmw_desired = zig_or_##Type(zig_atomicrmw_expected, arg); \
|
|
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
|
res = zig_atomicrmw_expected; \
|
|
} while (0)
|
|
#define zig_atomicrmw_xor_int128(res, obj, arg, order, Type, ReprType) do { \
|
|
zig_##Type zig_atomicrmw_expected; \
|
|
zig_##Type zig_atomicrmw_desired; \
|
|
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
|
do { \
|
|
zig_atomicrmw_desired = zig_xor_##Type(zig_atomicrmw_expected, arg); \
|
|
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
|
res = zig_atomicrmw_expected; \
|
|
} while (0)
|
|
#define zig_atomicrmw_min_int128(res, obj, arg, order, Type, ReprType) do { \
|
|
zig_##Type zig_atomicrmw_expected; \
|
|
zig_##Type zig_atomicrmw_desired; \
|
|
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
|
do { \
|
|
zig_atomicrmw_desired = zig_min_##Type(zig_atomicrmw_expected, arg); \
|
|
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
|
res = zig_atomicrmw_expected; \
|
|
} while (0)
|
|
#define zig_atomicrmw_max_int128(res, obj, arg, order, Type, ReprType) do { \
|
|
zig_##Type zig_atomicrmw_expected; \
|
|
zig_##Type zig_atomicrmw_desired; \
|
|
zig_atomic_load(zig_atomicrmw_expected, obj, zig_memory_order_relaxed, Type, ReprType); \
|
|
do { \
|
|
zig_atomicrmw_desired = zig_max_##Type(zig_atomicrmw_expected, arg); \
|
|
} while (!zig_cmpxchg_weak(obj, zig_atomicrmw_expected, zig_atomicrmw_desired, order, zig_memory_order_relaxed, Type, ReprType)); \
|
|
res = zig_atomicrmw_expected; \
|
|
} while (0)
|
|
|
|
#if (__STDC_VERSION__ >= 201112L || (zig_has_include(<stdatomic.h>) && !defined(zig_msvc))) && !defined(__STDC_NO_ATOMICS__)
|
|
#include <stdatomic.h>
|
|
typedef enum memory_order zig_memory_order;
|
|
#define zig_memory_order_relaxed memory_order_relaxed
|
|
#define zig_memory_order_acquire memory_order_acquire
|
|
#define zig_memory_order_release memory_order_release
|
|
#define zig_memory_order_acq_rel memory_order_acq_rel
|
|
#define zig_memory_order_seq_cst memory_order_seq_cst
|
|
#define zig_atomic(Type) _Atomic(Type)
|
|
#define zig_cmpxchg_strong( obj, expected, desired, succ, fail, Type, ReprType) atomic_compare_exchange_strong_explicit(obj, &(expected), desired, succ, fail)
|
|
#define zig_cmpxchg_weak( obj, expected, desired, succ, fail, Type, ReprType) atomic_compare_exchange_weak_explicit (obj, &(expected), desired, succ, fail)
|
|
#define zig_atomicrmw_xchg(res, obj, arg, order, Type, ReprType) res = atomic_exchange_explicit (obj, arg, order)
|
|
#define zig_atomicrmw_add(res, obj, arg, order, Type, ReprType) res = atomic_fetch_add_explicit (obj, arg, order)
|
|
#define zig_atomicrmw_sub(res, obj, arg, order, Type, ReprType) res = atomic_fetch_sub_explicit (obj, arg, order)
|
|
#define zig_atomicrmw_or(res, obj, arg, order, Type, ReprType) res = atomic_fetch_or_explicit (obj, arg, order)
|
|
#define zig_atomicrmw_xor(res, obj, arg, order, Type, ReprType) res = atomic_fetch_xor_explicit (obj, arg, order)
|
|
#define zig_atomicrmw_and(res, obj, arg, order, Type, ReprType) res = atomic_fetch_and_explicit (obj, arg, order)
|
|
#define zig_atomicrmw_nand(res, obj, arg, order, Type, ReprType) res = __atomic_fetch_nand(obj, arg, order)
|
|
#define zig_atomicrmw_min(res, obj, arg, order, Type, ReprType) res = __atomic_fetch_min (obj, arg, order)
|
|
#define zig_atomicrmw_max(res, obj, arg, order, Type, ReprType) res = __atomic_fetch_max (obj, arg, order)
|
|
#define zig_atomic_store( obj, arg, order, Type, ReprType) atomic_store_explicit (obj, arg, order)
|
|
#define zig_atomic_load(res, obj, order, Type, ReprType) res = atomic_load_explicit (obj, order)
|
|
#undef zig_atomicrmw_xchg_float
|
|
#define zig_atomicrmw_xchg_float zig_atomicrmw_xchg
|
|
#undef zig_atomicrmw_add_float
|
|
#define zig_atomicrmw_add_float zig_atomicrmw_add
|
|
#undef zig_atomicrmw_sub_float
|
|
#define zig_atomicrmw_sub_float zig_atomicrmw_sub
|
|
#elif defined(zig_gnuc)
|
|
typedef int zig_memory_order;
|
|
#define zig_memory_order_relaxed __ATOMIC_RELAXED
|
|
#define zig_memory_order_acquire __ATOMIC_ACQUIRE
|
|
#define zig_memory_order_release __ATOMIC_RELEASE
|
|
#define zig_memory_order_acq_rel __ATOMIC_ACQ_REL
|
|
#define zig_memory_order_seq_cst __ATOMIC_SEQ_CST
|
|
#define zig_atomic(Type) Type
|
|
#define zig_cmpxchg_strong( obj, expected, desired, succ, fail, Type, ReprType) __atomic_compare_exchange(obj, &(expected), &(desired), false, succ, fail)
|
|
#define zig_cmpxchg_weak( obj, expected, desired, succ, fail, Type, ReprType) __atomic_compare_exchange(obj, &(expected), &(desired), true, succ, fail)
|
|
#define zig_atomicrmw_xchg(res, obj, arg, order, Type, ReprType) __atomic_exchange(obj, &(arg), &(res), order)
|
|
#define zig_atomicrmw_add(res, obj, arg, order, Type, ReprType) res = __atomic_fetch_add (obj, arg, order)
|
|
#define zig_atomicrmw_sub(res, obj, arg, order, Type, ReprType) res = __atomic_fetch_sub (obj, arg, order)
|
|
#define zig_atomicrmw_or(res, obj, arg, order, Type, ReprType) res = __atomic_fetch_or (obj, arg, order)
|
|
#define zig_atomicrmw_xor(res, obj, arg, order, Type, ReprType) res = __atomic_fetch_xor (obj, arg, order)
|
|
#define zig_atomicrmw_and(res, obj, arg, order, Type, ReprType) res = __atomic_fetch_and (obj, arg, order)
|
|
#define zig_atomicrmw_nand(res, obj, arg, order, Type, ReprType) res = __atomic_fetch_nand(obj, arg, order)
|
|
#define zig_atomicrmw_min(res, obj, arg, order, Type, ReprType) res = __atomic_fetch_min (obj, arg, order)
|
|
#define zig_atomicrmw_max(res, obj, arg, order, Type, ReprType) res = __atomic_fetch_max (obj, arg, order)
|
|
#define zig_atomic_store( obj, arg, order, Type, ReprType) __atomic_store (obj, &(arg), order)
|
|
#define zig_atomic_load(res, obj, order, Type, ReprType) __atomic_load (obj, &(res), order)
|
|
#undef zig_atomicrmw_xchg_float
|
|
#define zig_atomicrmw_xchg_float zig_atomicrmw_xchg
|
|
#elif defined(zig_msvc) && defined(zig_x86)
|
|
#define zig_memory_order_relaxed 0
|
|
#define zig_memory_order_acquire 2
|
|
#define zig_memory_order_release 3
|
|
#define zig_memory_order_acq_rel 4
|
|
#define zig_memory_order_seq_cst 5
|
|
#define zig_atomic(Type) Type
|
|
#define zig_cmpxchg_strong( obj, expected, desired, succ, fail, Type, ReprType) zig_msvc_cmpxchg_##Type(obj, &(expected), desired)
|
|
#define zig_cmpxchg_weak( obj, expected, desired, succ, fail, Type, ReprType) zig_cmpxchg_strong(obj, expected, desired, succ, fail, Type, ReprType)
|
|
#define zig_atomicrmw_xchg(res, obj, arg, order, Type, ReprType) res = zig_msvc_atomicrmw_xchg_##Type(obj, arg)
|
|
#define zig_atomicrmw_add(res, obj, arg, order, Type, ReprType) res = zig_msvc_atomicrmw_add_ ##Type(obj, arg)
|
|
#define zig_atomicrmw_sub(res, obj, arg, order, Type, ReprType) res = zig_msvc_atomicrmw_sub_ ##Type(obj, arg)
|
|
#define zig_atomicrmw_or(res, obj, arg, order, Type, ReprType) res = zig_msvc_atomicrmw_or_ ##Type(obj, arg)
|
|
#define zig_atomicrmw_xor(res, obj, arg, order, Type, ReprType) res = zig_msvc_atomicrmw_xor_ ##Type(obj, arg)
|
|
#define zig_atomicrmw_and(res, obj, arg, order, Type, ReprType) res = zig_msvc_atomicrmw_and_ ##Type(obj, arg)
|
|
#define zig_atomicrmw_nand(res, obj, arg, order, Type, ReprType) res = zig_msvc_atomicrmw_nand_##Type(obj, arg)
|
|
#define zig_atomicrmw_min(res, obj, arg, order, Type, ReprType) res = zig_msvc_atomicrmw_min_ ##Type(obj, arg)
|
|
#define zig_atomicrmw_max(res, obj, arg, order, Type, ReprType) res = zig_msvc_atomicrmw_max_ ##Type(obj, arg)
|
|
#define zig_atomic_store( obj, arg, order, Type, ReprType) zig_msvc_atomic_store_ ##Type(obj, arg)
|
|
#define zig_atomic_load(res, obj, order, Type, ReprType) res = zig_msvc_atomic_load_ ##order##_##Type(obj)
|
|
/* TODO: zig_msvc && (zig_thumb || zig_aarch64) */
|
|
#else
|
|
#define zig_memory_order_relaxed 0
|
|
#define zig_memory_order_acquire 2
|
|
#define zig_memory_order_release 3
|
|
#define zig_memory_order_acq_rel 4
|
|
#define zig_memory_order_seq_cst 5
|
|
#define zig_atomic(Type) Type
|
|
#define zig_cmpxchg_strong( obj, expected, desired, succ, fail, Type, ReprType) zig_atomics_unavailable
|
|
#define zig_cmpxchg_weak( obj, expected, desired, succ, fail, Type, ReprType) zig_atomics_unavailable
|
|
#define zig_atomicrmw_xchg(res, obj, arg, order, Type, ReprType) zig_atomics_unavailable
|
|
#define zig_atomicrmw_add(res, obj, arg, order, Type, ReprType) zig_atomics_unavailable
|
|
#define zig_atomicrmw_sub(res, obj, arg, order, Type, ReprType) zig_atomics_unavailable
|
|
#define zig_atomicrmw_or(res, obj, arg, order, Type, ReprType) zig_atomics_unavailable
|
|
#define zig_atomicrmw_xor(res, obj, arg, order, Type, ReprType) zig_atomics_unavailable
|
|
#define zig_atomicrmw_and(res, obj, arg, order, Type, ReprType) zig_atomics_unavailable
|
|
#define zig_atomicrmw_nand(res, obj, arg, order, Type, ReprType) zig_atomics_unavailable
|
|
#define zig_atomicrmw_min(res, obj, arg, order, Type, ReprType) zig_atomics_unavailable
|
|
#define zig_atomicrmw_max(res, obj, arg, order, Type, ReprType) zig_atomics_unavailable
|
|
#define zig_atomic_store( obj, arg, order, Type, ReprType) zig_atomics_unavailable
|
|
#define zig_atomic_load(res, obj, order, Type, ReprType) zig_atomics_unavailable
|
|
#endif
|
|
|
|
#if defined(zig_msvc) && defined(zig_x86)
|
|
|
|
/* TODO: zig_msvc_atomic_load should load 32 bit without interlocked on x86, and load 64 bit without interlocked on x64 */
|
|
|
|
#define zig_msvc_atomics(ZigType, Type, SigType, suffix, iso_suffix) \
|
|
static inline bool zig_msvc_cmpxchg_##ZigType(Type volatile* obj, Type* expected, Type desired) { \
|
|
Type comparand = *expected; \
|
|
Type initial = _InterlockedCompareExchange##suffix((SigType volatile*)obj, (SigType)desired, (SigType)comparand); \
|
|
bool exchanged = initial == comparand; \
|
|
if (!exchanged) { \
|
|
*expected = initial; \
|
|
} \
|
|
return exchanged; \
|
|
} \
|
|
static inline Type zig_msvc_atomicrmw_xchg_##ZigType(Type volatile* obj, Type value) { \
|
|
return _InterlockedExchange##suffix((SigType volatile*)obj, (SigType)value); \
|
|
} \
|
|
static inline Type zig_msvc_atomicrmw_add_##ZigType(Type volatile* obj, Type value) { \
|
|
return _InterlockedExchangeAdd##suffix((SigType volatile*)obj, (SigType)value); \
|
|
} \
|
|
static inline Type zig_msvc_atomicrmw_sub_##ZigType(Type volatile* obj, Type value) { \
|
|
bool success = false; \
|
|
Type new; \
|
|
Type prev; \
|
|
while (!success) { \
|
|
prev = *obj; \
|
|
new = prev - value; \
|
|
success = zig_msvc_cmpxchg_##ZigType(obj, &prev, new); \
|
|
} \
|
|
return prev; \
|
|
} \
|
|
static inline Type zig_msvc_atomicrmw_or_##ZigType(Type volatile* obj, Type value) { \
|
|
return _InterlockedOr##suffix((SigType volatile*)obj, (SigType)value); \
|
|
} \
|
|
static inline Type zig_msvc_atomicrmw_xor_##ZigType(Type volatile* obj, Type value) { \
|
|
return _InterlockedXor##suffix((SigType volatile*)obj, (SigType)value); \
|
|
} \
|
|
static inline Type zig_msvc_atomicrmw_and_##ZigType(Type volatile* obj, Type value) { \
|
|
return _InterlockedAnd##suffix((SigType volatile*)obj, (SigType)value); \
|
|
} \
|
|
static inline Type zig_msvc_atomicrmw_nand_##ZigType(Type volatile* obj, Type value) { \
|
|
bool success = false; \
|
|
Type new; \
|
|
Type prev; \
|
|
while (!success) { \
|
|
prev = *obj; \
|
|
new = ~(prev & value); \
|
|
success = zig_msvc_cmpxchg_##ZigType(obj, &prev, new); \
|
|
} \
|
|
return prev; \
|
|
} \
|
|
static inline Type zig_msvc_atomicrmw_min_##ZigType(Type volatile* obj, Type value) { \
|
|
bool success = false; \
|
|
Type new; \
|
|
Type prev; \
|
|
while (!success) { \
|
|
prev = *obj; \
|
|
new = value < prev ? value : prev; \
|
|
success = zig_msvc_cmpxchg_##ZigType(obj, &prev, new); \
|
|
} \
|
|
return prev; \
|
|
} \
|
|
static inline Type zig_msvc_atomicrmw_max_##ZigType(Type volatile* obj, Type value) { \
|
|
bool success = false; \
|
|
Type new; \
|
|
Type prev; \
|
|
while (!success) { \
|
|
prev = *obj; \
|
|
new = value > prev ? value : prev; \
|
|
success = zig_msvc_cmpxchg_##ZigType(obj, &prev, new); \
|
|
} \
|
|
return prev; \
|
|
} \
|
|
static inline void zig_msvc_atomic_store_##ZigType(Type volatile* obj, Type value) { \
|
|
(void)_InterlockedExchange##suffix((SigType volatile*)obj, (SigType)value); \
|
|
} \
|
|
static inline Type zig_msvc_atomic_load_zig_memory_order_relaxed_##ZigType(Type volatile* obj) { \
|
|
return __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
|
|
} \
|
|
static inline Type zig_msvc_atomic_load_zig_memory_order_acquire_##ZigType(Type volatile* obj) { \
|
|
Type val = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
|
|
_ReadWriteBarrier(); \
|
|
return val; \
|
|
} \
|
|
static inline Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##ZigType(Type volatile* obj) { \
|
|
Type val = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
|
|
_ReadWriteBarrier(); \
|
|
return val; \
|
|
}
|
|
|
|
zig_msvc_atomics( u8, uint8_t, char, 8, 8)
|
|
zig_msvc_atomics( i8, int8_t, char, 8, 8)
|
|
zig_msvc_atomics(u16, uint16_t, short, 16, 16)
|
|
zig_msvc_atomics(i16, int16_t, short, 16, 16)
|
|
zig_msvc_atomics(u32, uint32_t, long, , 32)
|
|
zig_msvc_atomics(i32, int32_t, long, , 32)
|
|
|
|
#if defined(zig_x86_64)
|
|
zig_msvc_atomics(u64, uint64_t, __int64, 64, 64)
|
|
zig_msvc_atomics(i64, int64_t, __int64, 64, 64)
|
|
#endif
|
|
|
|
#define zig_msvc_flt_atomics(Type, SigType, suffix, iso_suffix) \
|
|
static inline bool zig_msvc_cmpxchg_##Type(zig_##Type volatile* obj, zig_##Type* expected, zig_##Type desired) { \
|
|
SigType exchange; \
|
|
SigType comparand; \
|
|
SigType initial; \
|
|
bool success; \
|
|
memcpy(&comparand, expected, sizeof(comparand)); \
|
|
memcpy(&exchange, &desired, sizeof(exchange)); \
|
|
initial = _InterlockedCompareExchange##suffix((SigType volatile*)obj, exchange, comparand); \
|
|
success = initial == comparand; \
|
|
if (!success) memcpy(expected, &initial, sizeof(*expected)); \
|
|
return success; \
|
|
} \
|
|
static inline void zig_msvc_atomic_store_##Type(zig_##Type volatile* obj, zig_##Type arg) { \
|
|
SigType value; \
|
|
memcpy(&value, &arg, sizeof(value)); \
|
|
(void)_InterlockedExchange##suffix((SigType volatile*)obj, value); \
|
|
} \
|
|
static inline zig_##Type zig_msvc_atomic_load_zig_memory_order_relaxed_##Type(zig_##Type volatile* obj) { \
|
|
zig_##Type result; \
|
|
SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
|
|
memcpy(&result, &initial, sizeof(result)); \
|
|
return result; \
|
|
} \
|
|
static inline zig_##Type zig_msvc_atomic_load_zig_memory_order_acquire_##Type(zig_##Type volatile* obj) { \
|
|
zig_##Type result; \
|
|
SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
|
|
_ReadWriteBarrier(); \
|
|
memcpy(&result, &initial, sizeof(result)); \
|
|
return result; \
|
|
} \
|
|
static inline zig_##Type zig_msvc_atomic_load_zig_memory_order_seq_cst_##Type(zig_##Type volatile* obj) { \
|
|
zig_##Type result; \
|
|
SigType initial = __iso_volatile_load##iso_suffix((SigType volatile*)obj); \
|
|
_ReadWriteBarrier(); \
|
|
memcpy(&result, &initial, sizeof(result)); \
|
|
return result; \
|
|
}
|
|
|
|
zig_msvc_flt_atomics(f32, long, , 32)
|
|
#if defined(zig_x86_64)
|
|
zig_msvc_flt_atomics(f64, int64_t, 64, 64)
|
|
#endif
|
|
|
|
#if defined(zig_x86_32)
|
|
static inline void zig_msvc_atomic_barrier() {
|
|
int32_t barrier;
|
|
__asm {
|
|
xchg barrier, eax
|
|
}
|
|
}
|
|
|
|
static inline void* zig_msvc_atomicrmw_xchg_p32(void volatile* obj, void* arg) {
|
|
return _InterlockedExchangePointer(obj, arg);
|
|
}
|
|
|
|
static inline void zig_msvc_atomic_store_p32(void volatile* obj, void* arg) {
|
|
(void)_InterlockedExchangePointer(obj, arg);
|
|
}
|
|
|
|
static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p32(void volatile* obj) {
|
|
return (void*)__iso_volatile_load32(obj);
|
|
}
|
|
|
|
static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p32(void volatile* obj) {
|
|
void* val = (void*)__iso_volatile_load32(obj);
|
|
_ReadWriteBarrier();
|
|
return val;
|
|
}
|
|
|
|
static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p32(void volatile* obj) {
|
|
return zig_msvc_atomic_load_zig_memory_order_acquire_p32(obj);
|
|
}
|
|
|
|
static inline bool zig_msvc_cmpxchg_p32(void volatile* obj, void* expected, void* desired) {
|
|
void* comparand = *(void**)expected;
|
|
void* initial = _InterlockedCompareExchangePointer(obj, desired, comparand);
|
|
bool success = initial == comparand;
|
|
if (!success) *(void**)expected = initial;
|
|
return success;
|
|
}
|
|
#else /* zig_x86_32 */
|
|
static inline void* zig_msvc_atomicrmw_xchg_p64(void volatile* obj, void* arg) {
|
|
return _InterlockedExchangePointer(obj, arg);
|
|
}
|
|
|
|
static inline void zig_msvc_atomic_store_p64(void volatile* obj, void* arg) {
|
|
(void)_InterlockedExchangePointer(obj, arg);
|
|
}
|
|
|
|
static inline void* zig_msvc_atomic_load_zig_memory_order_relaxed_p64(void volatile* obj) {
|
|
return (void*)__iso_volatile_load64(obj);
|
|
}
|
|
|
|
static inline void* zig_msvc_atomic_load_zig_memory_order_acquire_p64(void volatile* obj) {
|
|
void* val = (void*)__iso_volatile_load64(obj);
|
|
_ReadWriteBarrier();
|
|
return val;
|
|
}
|
|
|
|
static inline void* zig_msvc_atomic_load_zig_memory_order_seq_cst_p64(void volatile* obj) {
|
|
return zig_msvc_atomic_load_zig_memory_order_acquire_p64(obj);
|
|
}
|
|
|
|
static inline bool zig_msvc_cmpxchg_p64(void volatile* obj, void* expected, void* desired) {
|
|
void* comparand = *(void**)expected;
|
|
void* initial = _InterlockedCompareExchangePointer(obj, desired, comparand);
|
|
bool success = initial == comparand;
|
|
if (!success) *(void**)expected = initial;
|
|
return success;
|
|
}
|
|
|
|
static inline bool zig_msvc_cmpxchg_u128(zig_u128 volatile* obj, zig_u128* expected, zig_u128 desired) {
|
|
return _InterlockedCompareExchange128((__int64 volatile*)obj, (__int64)zig_hi_u128(desired), (__int64)zig_lo_u128(desired), (__int64*)expected);
|
|
}
|
|
|
|
static inline zig_u128 zig_msvc_atomic_load_u128(zig_u128 volatile* obj) {
|
|
zig_u128 expected = zig_make_u128(UINT64_C(0), UINT64_C(0));
|
|
(void)zig_cmpxchg_strong(obj, expected, expected, zig_memory_order_seq_cst, zig_memory_order_seq_cst, u128, zig_u128);
|
|
return expected;
|
|
}
|
|
|
|
static inline void zig_msvc_atomic_store_u128(zig_u128 volatile* obj, zig_u128 arg) {
|
|
zig_u128 expected = zig_make_u128(UINT64_C(0), UINT64_C(0));
|
|
while (!zig_cmpxchg_weak(obj, expected, arg, zig_memory_order_seq_cst, zig_memory_order_seq_cst, u128, zig_u128));
|
|
}
|
|
|
|
static inline bool zig_msvc_cmpxchg_i128(zig_i128 volatile* obj, zig_i128* expected, zig_i128 desired) {
|
|
return _InterlockedCompareExchange128((__int64 volatile*)obj, (__int64)zig_hi_i128(desired), (__int64)zig_lo_i128(desired), (__int64*)expected);
|
|
}
|
|
|
|
static inline zig_i128 zig_msvc_atomic_load_i128(zig_i128 volatile* obj) {
|
|
zig_i128 expected = zig_make_i128(INT64_C(0), UINT64_C(0));
|
|
(void)zig_cmpxchg_strong(obj, expected, expected, zig_memory_order_seq_cst, zig_memory_order_seq_cst, i128, zig_i128);
|
|
return expected;
|
|
}
|
|
|
|
static inline void zig_msvc_atomic_store_i128(zig_i128 volatile* obj, zig_i128 arg) {
|
|
zig_i128 expected = zig_make_i128(INT64_C(0), UINT64_C(0));
|
|
while (!zig_cmpxchg_weak(obj, expected, arg, zig_memory_order_seq_cst, zig_memory_order_seq_cst, i128, zig_i128));
|
|
}
|
|
|
|
#endif /* zig_x86_32 */
|
|
|
|
#endif /* zig_msvc && zig_x86 */
|
|
|
|
/* ======================== Special Case Intrinsics ========================= */
|
|
|
|
#if defined(zig_msvc)
|
|
#include <intrin.h>
|
|
#endif
|
|
|
|
#if defined(zig_thumb)
|
|
|
|
static inline void* zig_thumb_windows_teb(void) {
|
|
void* teb = 0;
|
|
#if defined(zig_msvc)
|
|
teb = (void*)_MoveFromCoprocessor(15, 0, 13, 0, 2);
|
|
#elif defined(zig_gnuc_asm)
|
|
__asm__ ("mrc p15, 0, %[ptr], c13, c0, 2" : [ptr] "=r" (teb));
|
|
#endif
|
|
return teb;
|
|
}
|
|
|
|
#elif defined(zig_aarch64)
|
|
|
|
static inline void* zig_aarch64_windows_teb(void) {
|
|
void* teb = 0;
|
|
#if defined(zig_msvc)
|
|
teb = (void*)__readx18qword(0x0);
|
|
#elif defined(zig_gnuc_asm)
|
|
__asm__ ("mov %[ptr], x18" : [ptr] "=r" (teb));
|
|
#endif
|
|
return teb;
|
|
}
|
|
|
|
#elif defined(zig_x86_32)
|
|
|
|
static inline void* zig_x86_windows_teb(void) {
|
|
void* teb = 0;
|
|
#if defined(zig_msvc)
|
|
teb = (void*)__readfsdword(0x18);
|
|
#elif defined(zig_gnuc_asm)
|
|
__asm__ ("movl %%fs:0x18, %[ptr]" : [ptr] "=r" (teb));
|
|
#endif
|
|
return teb;
|
|
}
|
|
|
|
#elif defined(zig_x86_64)
|
|
|
|
static inline void* zig_x86_64_windows_teb(void) {
|
|
void* teb = 0;
|
|
#if defined(zig_msvc)
|
|
teb = (void*)__readgsqword(0x30);
|
|
#elif defined(zig_gnuc_asm)
|
|
__asm__ ("movq %%gs:0x30, %[ptr]" : [ptr] "=r" (teb));
|
|
#endif
|
|
return teb;
|
|
}
|
|
|
|
#endif
|
|
|
|
#if defined(zig_x86)
|
|
|
|
static inline void zig_x86_cpuid(uint32_t leaf_id, uint32_t subid, uint32_t* eax, uint32_t* ebx, uint32_t* ecx, uint32_t* edx) {
|
|
#if defined(zig_msvc)
|
|
int cpu_info[4];
|
|
__cpuidex(cpu_info, leaf_id, subid);
|
|
*eax = (uint32_t)cpu_info[0];
|
|
*ebx = (uint32_t)cpu_info[1];
|
|
*ecx = (uint32_t)cpu_info[2];
|
|
*edx = (uint32_t)cpu_info[3];
|
|
#elif defined(zig_gnuc_asm)
|
|
__asm__("cpuid" : "=a"(*eax), "=b"(*ebx), "=c"(*ecx), "=d"(*edx) : "a"(leaf_id), "c"(subid));
|
|
#else
|
|
*eax = 0;
|
|
*ebx = 0;
|
|
*ecx = 0;
|
|
*edx = 0;
|
|
#endif
|
|
}
|
|
|
|
static inline uint32_t zig_x86_get_xcr0(void) {
|
|
#if defined(zig_msvc)
|
|
return (uint32_t)_xgetbv(0);
|
|
#elif defined(zig_gnuc_asm)
|
|
uint32_t eax;
|
|
uint32_t edx;
|
|
__asm__("xgetbv" : "=a"(eax), "=d"(edx) : "c"(0));
|
|
return eax;
|
|
#else
|
|
*eax = 0;
|
|
*ebx = 0;
|
|
*ecx = 0;
|
|
*edx = 0;
|
|
#endif
|
|
}
|
|
|
|
#endif
|