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 @@ -120,6 +120,61 @@ } #endif // __has_builtin(__builtin_addc) +// Subtract with borrow +template +inline constexpr cpp::enable_if_t< + cpp::is_integral_v && cpp::is_unsigned_v, T> +sub_with_borrow(T a, T b, T borrow_in, T &borrow_out) { + T tmp = a - b; + T diff = tmp - borrow_in; + borrow_out = (diff > tmp) || (tmp > a); + return diff; +} + +#if __has_builtin(__builtin_subc) +// https://clang.llvm.org/docs/LanguageExtensions.html#multiprecision-arithmetic-builtins + +template <> +inline unsigned char sub_with_borrow(unsigned char a, + unsigned char b, + unsigned char borrow_in, + unsigned char &borrow_out) { + return __builtin_subcb(a, b, borrow_in, &borrow_out); +} + +template <> +inline unsigned short +sub_with_borrow(unsigned short a, unsigned short b, + unsigned short borrow_in, + unsigned short &borrow_out) { + return __builtin_subcs(a, b, borrow_in, &borrow_out); +} + +template <> +inline unsigned int sub_with_borrow(unsigned int a, + unsigned int b, + unsigned int borrow_in, + unsigned int &borrow_out) { + return __builtin_subc(a, b, borrow_in, &borrow_out); +} + +template <> +inline unsigned long sub_with_borrow(unsigned long a, + unsigned long b, + unsigned long borrow_in, + unsigned long &borrow_out) { + return __builtin_subcl(a, b, borrow_in, &borrow_out); +} + +template <> +inline unsigned long long +sub_with_borrow(unsigned long long a, unsigned long long b, + unsigned long long borrow_in, + unsigned long long &borrow_out) { + return __builtin_subcll(a, b, borrow_in, &borrow_out); +} +#endif // __has_builtin(__builtin_subc) + } // namespace __llvm_libc #endif // LLVM_LIBC_SRC_SUPPORT_BUILTIN_WRAPPERS_H