diff --git a/libc/src/__support/builtin_wrappers.h b/libc/src/__support/builtin_wrappers.h --- a/libc/src/__support/builtin_wrappers.h +++ b/libc/src/__support/builtin_wrappers.h @@ -64,6 +64,58 @@ return __internal::clz(val); } +// Add with carry +template +inline constexpr T add_with_carry(T a, T b, T carry_in, T &carry_out) { + T tmp = a + carry_in; + T sum = b + tmp; + carry_out = (sum < b) | (tmp < a); + return sum; +} + +#if __has_builtin(__builtin_addc) +// https://clang.llvm.org/docs/LanguageExtensions.html#multiprecision-arithmetic-builtins + +template <> +inline unsigned char add_with_carry(unsigned char a, + unsigned char b, + unsigned char carry_in, + unsigned char &carry_out) { + return __builtin_addcb(a, b, carry_in, &carry_out); +} + +template <> +inline unsigned short +add_with_carry(unsigned short a, unsigned short b, + unsigned short carry_in, + unsigned short &carry_out) { + return __builtin_addcs(a, b, carry_in, &carry_out); +} + +template <> +inline unsigned int add_with_carry(unsigned int a, unsigned int b, + unsigned int carry_in, + unsigned int &carry_out) { + return __builtin_addc(a, b, carry_in, &carry_out); +} + +template <> +inline unsigned long add_with_carry(unsigned long a, + unsigned long b, + unsigned long carry_in, + unsigned long &carry_out) { + return __builtin_addcl(a, b, carry_in, &carry_out); +} + +template <> +inline unsigned long long +add_with_carry(unsigned long long a, unsigned long long b, + unsigned long long carry_in, + unsigned long long &carry_out) { + return __builtin_addcll(a, b, carry_in, &carry_out); +} +#endif // __has_builtin(__builtin_addc) + } // namespace __llvm_libc #endif // LLVM_LIBC_SRC_SUPPORT_BUILTIN_WRAPPERS_H