--- /dev/null
+#ifndef HAVE_SAT_ARITH
+#define HAVE_SAT_ARITH
+
+#include <stdint-gcc.h>
+#include <stdbool.h>
+
+/******************************************************************************/
+/* Saturation Add (unsigned and signed) */
+/******************************************************************************/
+#define DEF_SAT_U_ADD_FMT_1(T) \
+T __attribute__((noinline)) \
+sat_u_add_##T##_fmt_1 (T x, T y) \
+{ \
+ return (x + y) | (-(T)((T)(x + y) < x)); \
+}
+
+#define DEF_SAT_U_ADD_FMT_2(T) \
+T __attribute__((noinline)) \
+sat_u_add_##T##_fmt_2 (T x, T y) \
+{ \
+ return (T)(x + y) >= x ? (x + y) : -1; \
+}
+
+#define DEF_SAT_U_ADD_FMT_3(T) \
+T __attribute__((noinline)) \
+sat_u_add_##T##_fmt_3 (T x, T y) \
+{ \
+ T ret; \
+ T overflow = __builtin_add_overflow (x, y, &ret); \
+ return (T)(-overflow) | ret; \
+}
+
+#define DEF_SAT_U_ADD_FMT_4(T) \
+T __attribute__((noinline)) \
+sat_u_add_##T##_fmt_4 (T x, T y) \
+{ \
+ T ret; \
+ return __builtin_add_overflow (x, y, &ret) ? -1 : ret; \
+}
+
+#define DEF_SAT_U_ADD_FMT_5(T) \
+T __attribute__((noinline)) \
+sat_u_add_##T##_fmt_5 (T x, T y) \
+{ \
+ T ret; \
+ return __builtin_add_overflow (x, y, &ret) == 0 ? ret : -1; \
+}
+
+#define DEF_SAT_U_ADD_FMT_6(T) \
+T __attribute__((noinline)) \
+sat_u_add_##T##_fmt_6 (T x, T y) \
+{ \
+ return (T)(x + y) < x ? -1 : (x + y); \
+}
+
+#define RUN_SAT_U_ADD_FMT_1(T, x, y) sat_u_add_##T##_fmt_1(x, y)
+#define RUN_SAT_U_ADD_FMT_2(T, x, y) sat_u_add_##T##_fmt_2(x, y)
+#define RUN_SAT_U_ADD_FMT_3(T, x, y) sat_u_add_##T##_fmt_3(x, y)
+#define RUN_SAT_U_ADD_FMT_4(T, x, y) sat_u_add_##T##_fmt_4(x, y)
+#define RUN_SAT_U_ADD_FMT_5(T, x, y) sat_u_add_##T##_fmt_5(x, y)
+#define RUN_SAT_U_ADD_FMT_6(T, x, y) sat_u_add_##T##_fmt_6(x, y)
+
+#define DEF_SAT_U_ADD_IMM_FMT_1(T, IMM) \
+T __attribute__((noinline)) \
+sat_u_add_imm##IMM##_##T##_fmt_1 (T x) \
+{ \
+ return (T)(x + IMM) >= x ? (x + IMM) : -1; \
+}
+
+#define DEF_SAT_U_ADD_IMM_FMT_2(T, IMM) \
+T __attribute__((noinline)) \
+sat_u_add_imm##IMM##_##T##_fmt_2 (T x) \
+{ \
+ return (T)(x + IMM) < x ? -1 : (x + IMM); \
+}
+
+#define DEF_SAT_U_ADD_IMM_FMT_3(T, IMM) \
+T __attribute__((noinline)) \
+sat_u_add_imm##IMM##_##T##_fmt_3 (T x) \
+{ \
+ T ret; \
+ return __builtin_add_overflow (x, IMM, &ret) ? -1 : ret; \
+}
+
+#define DEF_SAT_U_ADD_IMM_FMT_4(T, IMM) \
+T __attribute__((noinline)) \
+sat_u_add_imm##IMM##_##T##_fmt_4 (T x) \
+{ \
+ T ret; \
+ return __builtin_add_overflow (x, IMM, &ret) == 0 ? ret : -1; \
+}
+
+#define DEF_SAT_U_ADD_IMM_TYPE_CHECK_FMT_1(T, IMM) \
+T __attribute__((noinline)) \
+sat_u_add_imm_type_check##_##T##_fmt_1 (T x) \
+{ \
+ T ret; \
+ return __builtin_add_overflow (x, IMM, &ret) ? -1 : ret; \
+}
+
+#define DEF_SAT_U_ADD_IMM_TYPE_CHECK_FMT_2(T, IMM) \
+T __attribute__((noinline)) \
+sat_u_add_imm_type_check##_##T##_fmt_2 (T x) \
+{ \
+ T ret; \
+ return __builtin_add_overflow (x, IMM, &ret) == 0 ? ret : -1; \
+}
+
+#define RUN_SAT_U_ADD_IMM_FMT_1(T, x, IMM, expect) \
+ if (sat_u_add_imm##IMM##_##T##_fmt_1(x) != expect) __builtin_abort ()
+
+#define RUN_SAT_U_ADD_IMM_FMT_2(T, x, IMM, expect) \
+ if (sat_u_add_imm##IMM##_##T##_fmt_2(x) != expect) __builtin_abort ()
+
+#define RUN_SAT_U_ADD_IMM_FMT_3(T, x, IMM, expect) \
+ if (sat_u_add_imm##IMM##_##T##_fmt_3(x) != expect) __builtin_abort ()
+
+#define RUN_SAT_U_ADD_IMM_FMT_4(T, x, IMM, expect) \
+ if (sat_u_add_imm##IMM##_##T##_fmt_4(x) != expect) __builtin_abort ()
+
+#define DEF_SAT_S_ADD_FMT_1(T, UT, MIN, MAX) \
+T __attribute__((noinline)) \
+sat_s_add_##T##_fmt_1 (T x, T y) \
+{ \
+ T sum = (UT)x + (UT)y; \
+ return (x ^ y) < 0 \
+ ? sum \
+ : (sum ^ x) >= 0 \
+ ? sum \
+ : x < 0 ? MIN : MAX; \
+}
+#define DEF_SAT_S_ADD_FMT_1_WRAP(T, UT, MIN, MAX) \
+ DEF_SAT_S_ADD_FMT_1(T, UT, MIN, MAX)
+
+#define DEF_SAT_S_ADD_FMT_2(T, UT, MIN, MAX) \
+T __attribute__((noinline)) \
+sat_s_add_##T##_fmt_2 (T x, T y) \
+{ \
+ T sum = (UT)x + (UT)y; \
+ if ((x ^ y) < 0 || (sum ^ x) >= 0) \
+ return sum; \
+ return x < 0 ? MIN : MAX; \
+}
+#define DEF_SAT_S_ADD_FMT_2_WRAP(T, UT, MIN, MAX) \
+ DEF_SAT_S_ADD_FMT_2(T, UT, MIN, MAX)
+
+#define DEF_SAT_S_ADD_FMT_3(T, UT, MIN, MAX) \
+T __attribute__((noinline)) \
+sat_s_add_##T##_fmt_3 (T x, T y) \
+{ \
+ T sum; \
+ bool overflow = __builtin_add_overflow (x, y, &sum); \
+ return overflow ? x < 0 ? MIN : MAX : sum; \
+}
+#define DEF_SAT_S_ADD_FMT_3_WRAP(T, UT, MIN, MAX) \
+ DEF_SAT_S_ADD_FMT_3(T, UT, MIN, MAX)
+
+#define DEF_SAT_S_ADD_FMT_4(T, UT, MIN, MAX) \
+T __attribute__((noinline)) \
+sat_s_add_##T##_fmt_4 (T x, T y) \
+{ \
+ T sum; \
+ bool overflow = __builtin_add_overflow (x, y, &sum); \
+ return !overflow ? sum : x < 0 ? MIN : MAX; \
+}
+#define DEF_SAT_S_ADD_FMT_4_WRAP(T, UT, MIN, MAX) \
+ DEF_SAT_S_ADD_FMT_4(T, UT, MIN, MAX)
+
+#define RUN_SAT_S_ADD_FMT_1(T, x, y) sat_s_add_##T##_fmt_1(x, y)
+#define RUN_SAT_S_ADD_FMT_1_WRAP(T, x, y) RUN_SAT_S_ADD_FMT_1(T, x, y)
+
+#define RUN_SAT_S_ADD_FMT_2(T, x, y) sat_s_add_##T##_fmt_2(x, y)
+#define RUN_SAT_S_ADD_FMT_2_WRAP(T, x, y) RUN_SAT_S_ADD_FMT_2(T, x, y)
+
+#define RUN_SAT_S_ADD_FMT_3(T, x, y) sat_s_add_##T##_fmt_3(x, y)
+#define RUN_SAT_S_ADD_FMT_3_WRAP(T, x, y) RUN_SAT_S_ADD_FMT_3(T, x, y)
+
+#define RUN_SAT_S_ADD_FMT_4(T, x, y) sat_s_add_##T##_fmt_4(x, y)
+#define RUN_SAT_S_ADD_FMT_4_WRAP(T, x, y) RUN_SAT_S_ADD_FMT_4(T, x, y)
+
+#define DEF_SAT_S_ADD_IMM_FMT_1(INDEX, T, UT, IMM, MIN, MAX) \
+T __attribute__((noinline)) \
+sat_s_add_imm_##T##_fmt_1##_##INDEX (T x) \
+{ \
+ T sum = (UT)x + (UT)IMM; \
+ return (x ^ IMM) < 0 \
+ ? sum \
+ : (sum ^ x) >= 0 \
+ ? sum \
+ : x < 0 ? MIN : MAX; \
+}
+
+#define RUN_SAT_S_ADD_IMM_FMT_1(INDEX, T, x, expect) \
+ if (sat_s_add_imm##_##T##_fmt_1##_##INDEX(x) != expect) __builtin_abort ()
+
+/******************************************************************************/
+/* Saturation Sub (Unsigned and Signed) */
+/******************************************************************************/
+#define DEF_SAT_U_SUB_FMT_1(T) \
+T __attribute__((noinline)) \
+sat_u_sub_##T##_fmt_1 (T x, T y) \
+{ \
+ return (x - y) & (-(T)(x >= y)); \
+}
+
+#define DEF_SAT_U_SUB_FMT_2(T) \
+T __attribute__((noinline)) \
+sat_u_sub_##T##_fmt_2 (T x, T y) \
+{ \
+ return (x - y) & (-(T)(x > y)); \
+}
+
+#define DEF_SAT_U_SUB_FMT_3(T) \
+T __attribute__((noinline)) \
+sat_u_sub_##T##_fmt_3 (T x, T y) \
+{ \
+ return x > y ? x - y : 0; \
+}
+
+#define DEF_SAT_U_SUB_FMT_4(T) \
+T __attribute__((noinline)) \
+sat_u_sub_##T##_fmt_4 (T x, T y) \
+{ \
+ return x >= y ? x - y : 0; \
+}
+
+#define DEF_SAT_U_SUB_FMT_5(T) \
+T __attribute__((noinline)) \
+sat_u_sub_##T##_fmt_5 (T x, T y) \
+{ \
+ return x < y ? 0 : x - y; \
+}
+
+#define DEF_SAT_U_SUB_FMT_6(T) \
+T __attribute__((noinline)) \
+sat_u_sub_##T##_fmt_6 (T x, T y) \
+{ \
+ return x <= y ? 0 : x - y; \
+}
+
+#define DEF_SAT_U_SUB_FMT_7(T) \
+T __attribute__((noinline)) \
+sat_u_sub_##T##_fmt_7 (T x, T y) \
+{ \
+ T ret; \
+ T overflow = __builtin_sub_overflow (x, y, &ret); \
+ return ret & (T)(overflow - 1); \
+}
+
+#define DEF_SAT_U_SUB_FMT_8(T) \
+T __attribute__((noinline)) \
+sat_u_sub_##T##_fmt_8 (T x, T y) \
+{ \
+ T ret; \
+ T overflow = __builtin_sub_overflow (x, y, &ret); \
+ return ret & (T)-(!overflow); \
+}
+
+#define DEF_SAT_U_SUB_FMT_9(T) \
+T __attribute__((noinline)) \
+sat_u_sub_##T##_fmt_9 (T x, T y) \
+{ \
+ T ret; \
+ T overflow = __builtin_sub_overflow (x, y, &ret); \
+ return overflow ? 0 : ret; \
+}
+
+#define DEF_SAT_U_SUB_FMT_10(T) \
+T __attribute__((noinline)) \
+sat_u_sub_##T##_fmt_10 (T x, T y) \
+{ \
+ T ret; \
+ T overflow = __builtin_sub_overflow (x, y, &ret); \
+ return !overflow ? ret : 0; \
+}
+
+#define DEF_SAT_U_SUB_FMT_11(T) \
+T __attribute__((noinline)) \
+sat_u_sub_##T##_fmt_11 (T x, T y) \
+{ \
+ T ret; \
+ bool overflow = __builtin_sub_overflow (x, y, &ret); \
+ return overflow ? 0 : ret; \
+}
+
+#define DEF_SAT_U_SUB_FMT_12(T) \
+T __attribute__((noinline)) \
+sat_u_sub_##T##_fmt_12 (T x, T y) \
+{ \
+ T ret; \
+ bool overflow = __builtin_sub_overflow (x, y, &ret); \
+ return !overflow ? ret : 0; \
+}
+
+#define DEF_SAT_U_SUB_IMM_FMT_1(T, IMM) \
+T __attribute__((noinline)) \
+sat_u_sub_imm##IMM##_##T##_fmt_1 (T y) \
+{ \
+ return (T)IMM >= y ? (T)IMM - y : 0; \
+}
+
+#define DEF_SAT_U_SUB_IMM_FMT_2(T, IMM) \
+T __attribute__((noinline)) \
+sat_u_sub_imm##IMM##_##T##_fmt_2 (T x) \
+{ \
+ return x >= (T)IMM ? x - (T)IMM : 0; \
+}
+
+#define DEF_SAT_U_SUB_IMM_FMT_3(T, IMM) \
+T __attribute__((noinline)) \
+sat_u_sub_imm##IMM##_##T##_fmt_3 (T y) \
+{ \
+ return (T)IMM > y ? (T)IMM - y : 0; \
+}
+
+#define DEF_SAT_U_SUB_IMM_FMT_4(T, IMM) \
+T __attribute__((noinline)) \
+sat_u_sub_imm##IMM##_##T##_fmt_4 (T x) \
+{ \
+ return x > (T)IMM ? x - (T)IMM : 0; \
+}
+
+#define RUN_SAT_U_SUB_FMT_1(T, x, y) sat_u_sub_##T##_fmt_1(x, y)
+#define RUN_SAT_U_SUB_FMT_2(T, x, y) sat_u_sub_##T##_fmt_2(x, y)
+#define RUN_SAT_U_SUB_FMT_3(T, x, y) sat_u_sub_##T##_fmt_3(x, y)
+#define RUN_SAT_U_SUB_FMT_4(T, x, y) sat_u_sub_##T##_fmt_4(x, y)
+#define RUN_SAT_U_SUB_FMT_5(T, x, y) sat_u_sub_##T##_fmt_5(x, y)
+#define RUN_SAT_U_SUB_FMT_6(T, x, y) sat_u_sub_##T##_fmt_6(x, y)
+#define RUN_SAT_U_SUB_FMT_7(T, x, y) sat_u_sub_##T##_fmt_7(x, y)
+#define RUN_SAT_U_SUB_FMT_8(T, x, y) sat_u_sub_##T##_fmt_8(x, y)
+#define RUN_SAT_U_SUB_FMT_9(T, x, y) sat_u_sub_##T##_fmt_9(x, y)
+#define RUN_SAT_U_SUB_FMT_10(T, x, y) sat_u_sub_##T##_fmt_10(x, y)
+#define RUN_SAT_U_SUB_FMT_11(T, x, y) sat_u_sub_##T##_fmt_11(x, y)
+#define RUN_SAT_U_SUB_FMT_12(T, x, y) sat_u_sub_##T##_fmt_12(x, y)
+
+#define RUN_SAT_U_SUB_IMM_FMT_1(T, IMM, y, expect) \
+ if (sat_u_sub_imm##IMM##_##T##_fmt_1(y) != expect) __builtin_abort ()
+#define RUN_SAT_U_SUB_IMM_FMT_2(T, x, IMM, expect) \
+ if (sat_u_sub_imm##IMM##_##T##_fmt_2(x) != expect) __builtin_abort ()
+#define RUN_SAT_U_SUB_IMM_FMT_3(T, IMM, y, expect) \
+ if (sat_u_sub_imm##IMM##_##T##_fmt_3(y) != expect) __builtin_abort ()
+#define RUN_SAT_U_SUB_IMM_FMT_4(T, x, IMM, expect) \
+ if (sat_u_sub_imm##IMM##_##T##_fmt_4(x) != expect) __builtin_abort ()
+
+#define DEF_SAT_U_SUB_IMM_TYPE_CHECK_FMT_1(INDEX, T, IMM) \
+T __attribute__((noinline)) \
+sat_u_sub_imm_type_check##_##INDEX##_##T##_fmt_1 (T y) \
+{ \
+ return IMM >= y ? IMM - y : 0; \
+}
+
+#define DEF_SAT_U_SUB_IMM_TYPE_CHECK_FMT_2(INDEX, T, IMM) \
+T __attribute__((noinline)) \
+sat_u_sub_imm_type_check##_##INDEX##_##T##_fmt_2 (T y) \
+{ \
+ return IMM > y ? IMM - y : 0; \
+}
+
+#define DEF_SAT_U_SUB_IMM_TYPE_CHECK_FMT_3(INDEX, T, IMM) \
+T __attribute__((noinline)) \
+sat_u_sub_imm_type_check##_##INDEX##_##T##_fmt_3 (T x) \
+{ \
+ return x >= IMM ? x - IMM : 0; \
+}
+
+#define DEF_SAT_U_SUB_IMM_TYPE_CHECK_FMT_4(INDEX, T, IMM) \
+T __attribute__((noinline)) \
+sat_u_sub_imm_type_check##_##INDEX##_##T##_fmt_4 (T x) \
+{ \
+ return x > IMM ? x - IMM : 0; \
+}
+
+#define DEF_SAT_S_SUB_FMT_1(T, UT, MIN, MAX) \
+T __attribute__((noinline)) \
+sat_s_sub_##T##_fmt_1 (T x, T y) \
+{ \
+ T minus = (UT)x - (UT)y; \
+ return (x ^ y) >= 0 \
+ ? minus \
+ : (minus ^ x) >= 0 \
+ ? minus \
+ : x < 0 ? MIN : MAX; \
+}
+#define DEF_SAT_S_SUB_FMT_1_WRAP(T, UT, MIN, MAX) \
+ DEF_SAT_S_SUB_FMT_1(T, UT, MIN, MAX)
+
+#define DEF_SAT_S_SUB_FMT_2(T, UT, MIN, MAX) \
+T __attribute__((noinline)) \
+sat_s_sub_##T##_fmt_2 (T x, T y) \
+{ \
+ T minus = (UT)x - (UT)y; \
+ if ((x ^ y) >= 0 || (minus ^ x) >= 0) \
+ return minus; \
+ return x < 0 ? MIN : MAX; \
+}
+#define DEF_SAT_S_SUB_FMT_2_WRAP(T, UT, MIN, MAX) \
+ DEF_SAT_S_SUB_FMT_2(T, UT, MIN, MAX)
+
+#define DEF_SAT_S_SUB_FMT_3(T, UT, MIN, MAX) \
+T __attribute__((noinline)) \
+sat_s_sub_##T##_fmt_3 (T x, T y) \
+{ \
+ T minus; \
+ bool overflow = __builtin_sub_overflow (x, y, &minus); \
+ return overflow ? x < 0 ? MIN : MAX : minus; \
+}
+#define DEF_SAT_S_SUB_FMT_3_WRAP(T, UT, MIN, MAX) \
+ DEF_SAT_S_SUB_FMT_3(T, UT, MIN, MAX)
+
+#define DEF_SAT_S_SUB_FMT_4(T, UT, MIN, MAX) \
+T __attribute__((noinline)) \
+sat_s_sub_##T##_fmt_4 (T x, T y) \
+{ \
+ T minus; \
+ bool overflow = __builtin_sub_overflow (x, y, &minus); \
+ return !overflow ? minus : x < 0 ? MIN : MAX; \
+}
+#define DEF_SAT_S_SUB_FMT_4_WRAP(T, UT, MIN, MAX) \
+ DEF_SAT_S_SUB_FMT_4(T, UT, MIN, MAX)
+
+#define RUN_SAT_S_SUB_FMT_1(T, x, y) sat_s_sub_##T##_fmt_1(x, y)
+#define RUN_SAT_S_SUB_FMT_1_WRAP(T, x, y) RUN_SAT_S_SUB_FMT_1(T, x, y)
+
+#define RUN_SAT_S_SUB_FMT_2(T, x, y) sat_s_sub_##T##_fmt_2(x, y)
+#define RUN_SAT_S_SUB_FMT_2_WRAP(T, x, y) RUN_SAT_S_SUB_FMT_2(T, x, y)
+
+#define RUN_SAT_S_SUB_FMT_3(T, x, y) sat_s_sub_##T##_fmt_3(x, y)
+#define RUN_SAT_S_SUB_FMT_3_WRAP(T, x, y) RUN_SAT_S_SUB_FMT_3(T, x, y)
+
+#define RUN_SAT_S_SUB_FMT_4(T, x, y) sat_s_sub_##T##_fmt_4(x, y)
+#define RUN_SAT_S_SUB_FMT_4_WRAP(T, x, y) RUN_SAT_S_SUB_FMT_4(T, x, y)
+
+/******************************************************************************/
+/* Saturation Truncate (unsigned and signed) */
+/******************************************************************************/
+
+#define DEF_SAT_U_TRUNC_FMT_1(NT, WT) \
+NT __attribute__((noinline)) \
+sat_u_trunc_##WT##_to_##NT##_fmt_1 (WT x) \
+{ \
+ bool overflow = x > (WT)(NT)(-1); \
+ return ((NT)x) | (NT)-overflow; \
+}
+#define DEF_SAT_U_TRUNC_FMT_1_WRAP(NT, WT) DEF_SAT_U_TRUNC_FMT_1(NT, WT)
+
+#define DEF_SAT_U_TRUNC_FMT_2(NT, WT) \
+NT __attribute__((noinline)) \
+sat_u_trunc_##WT##_to_##NT##_fmt_2 (WT x) \
+{ \
+ WT max = (WT)(NT)-1; \
+ return x > max ? (NT) max : (NT)x; \
+}
+#define DEF_SAT_U_TRUNC_FMT_2_WRAP(NT, WT) DEF_SAT_U_TRUNC_FMT_2(NT, WT)
+
+#define DEF_SAT_U_TRUNC_FMT_3(NT, WT) \
+NT __attribute__((noinline)) \
+sat_u_trunc_##WT##_to_##NT##_fmt_3 (WT x) \
+{ \
+ WT max = (WT)(NT)-1; \
+ return x <= max ? (NT)x : (NT) max; \
+}
+#define DEF_SAT_U_TRUNC_FMT_3_WRAP(NT, WT) DEF_SAT_U_TRUNC_FMT_3(NT, WT)
+
+#define DEF_SAT_U_TRUNC_FMT_4(NT, WT) \
+NT __attribute__((noinline)) \
+sat_u_trunc_##WT##_to_##NT##_fmt_4 (WT x) \
+{ \
+ bool not_overflow = x <= (WT)(NT)(-1); \
+ return ((NT)x) | (NT)((NT)not_overflow - 1); \
+}
+#define DEF_SAT_U_TRUNC_FMT_4_WRAP(NT, WT) DEF_SAT_U_TRUNC_FMT_4(NT, WT)
+
+#define RUN_SAT_U_TRUNC_FMT_1(NT, WT, x) sat_u_trunc_##WT##_to_##NT##_fmt_1 (x)
+#define RUN_SAT_U_TRUNC_FMT_1_WRAP(NT, WT, x) RUN_SAT_U_TRUNC_FMT_1(NT, WT, x)
+
+#define RUN_SAT_U_TRUNC_FMT_2(NT, WT, x) sat_u_trunc_##WT##_to_##NT##_fmt_2 (x)
+#define RUN_SAT_U_TRUNC_FMT_2_WRAP(NT, WT, x) RUN_SAT_U_TRUNC_FMT_2(NT, WT, x)
+
+#define RUN_SAT_U_TRUNC_FMT_3(NT, WT, x) sat_u_trunc_##WT##_to_##NT##_fmt_3 (x)
+#define RUN_SAT_U_TRUNC_FMT_3_WRAP(NT, WT, x) RUN_SAT_U_TRUNC_FMT_3(NT, WT, x)
+
+#define RUN_SAT_U_TRUNC_FMT_4(NT, WT, x) sat_u_trunc_##WT##_to_##NT##_fmt_4 (x)
+#define RUN_SAT_U_TRUNC_FMT_4_WRAP(NT, WT, x) RUN_SAT_U_TRUNC_FMT_4(NT, WT, x)
+
+#define DEF_SAT_S_TRUNC_FMT_1(NT, WT, NT_MIN, NT_MAX) \
+NT __attribute__((noinline)) \
+sat_s_trunc_##WT##_to_##NT##_fmt_1 (WT x) \
+{ \
+ NT trunc = (NT)x; \
+ return (WT)NT_MIN <= x && x <= (WT)NT_MAX \
+ ? trunc \
+ : x < 0 ? NT_MIN : NT_MAX; \
+}
+#define DEF_SAT_S_TRUNC_FMT_1_WRAP(NT, WT, NT_MIN, NT_MAX) \
+ DEF_SAT_S_TRUNC_FMT_1(NT, WT, NT_MIN, NT_MAX)
+
+#define DEF_SAT_S_TRUNC_FMT_2(NT, WT, NT_MIN, NT_MAX) \
+NT __attribute__((noinline)) \
+sat_s_trunc_##WT##_to_##NT##_fmt_2 (WT x) \
+{ \
+ NT trunc = (NT)x; \
+ return (WT)NT_MIN < x && x < (WT)NT_MAX \
+ ? trunc \
+ : x < 0 ? NT_MIN : NT_MAX; \
+}
+#define DEF_SAT_S_TRUNC_FMT_2_WRAP(NT, WT, NT_MIN, NT_MAX) \
+ DEF_SAT_S_TRUNC_FMT_2(NT, WT, NT_MIN, NT_MAX)
+
+#define DEF_SAT_S_TRUNC_FMT_3(NT, WT, NT_MIN, NT_MAX) \
+NT __attribute__((noinline)) \
+sat_s_trunc_##WT##_to_##NT##_fmt_3 (WT x) \
+{ \
+ NT trunc = (NT)x; \
+ return (WT)NT_MIN < x && x <= (WT)NT_MAX \
+ ? trunc \
+ : x < 0 ? NT_MIN : NT_MAX; \
+}
+#define DEF_SAT_S_TRUNC_FMT_3_WRAP(NT, WT, NT_MIN, NT_MAX) \
+ DEF_SAT_S_TRUNC_FMT_3(NT, WT, NT_MIN, NT_MAX)
+
+#define DEF_SAT_S_TRUNC_FMT_4(NT, WT, NT_MIN, NT_MAX) \
+NT __attribute__((noinline)) \
+sat_s_trunc_##WT##_to_##NT##_fmt_4 (WT x) \
+{ \
+ NT trunc = (NT)x; \
+ return (WT)NT_MIN <= x && x < (WT)NT_MAX \
+ ? trunc \
+ : x < 0 ? NT_MIN : NT_MAX; \
+}
+#define DEF_SAT_S_TRUNC_FMT_4_WRAP(NT, WT, NT_MIN, NT_MAX) \
+ DEF_SAT_S_TRUNC_FMT_4(NT, WT, NT_MIN, NT_MAX)
+
+#define DEF_SAT_S_TRUNC_FMT_5(NT, WT, NT_MIN, NT_MAX) \
+NT __attribute__((noinline)) \
+sat_s_trunc_##WT##_to_##NT##_fmt_5 (WT x) \
+{ \
+ NT trunc = (NT)x; \
+ return (WT)NT_MIN > x || x > (WT)NT_MAX \
+ ? x < 0 ? NT_MIN : NT_MAX \
+ : trunc; \
+}
+#define DEF_SAT_S_TRUNC_FMT_5_WRAP(NT, WT, NT_MIN, NT_MAX) \
+ DEF_SAT_S_TRUNC_FMT_5(NT, WT, NT_MIN, NT_MAX)
+
+#define DEF_SAT_S_TRUNC_FMT_6(NT, WT, NT_MIN, NT_MAX) \
+NT __attribute__((noinline)) \
+sat_s_trunc_##WT##_to_##NT##_fmt_6 (WT x) \
+{ \
+ NT trunc = (NT)x; \
+ return (WT)NT_MIN >= x || x > (WT)NT_MAX \
+ ? x < 0 ? NT_MIN : NT_MAX \
+ : trunc; \
+}
+#define DEF_SAT_S_TRUNC_FMT_6_WRAP(NT, WT, NT_MIN, NT_MAX) \
+ DEF_SAT_S_TRUNC_FMT_6(NT, WT, NT_MIN, NT_MAX)
+
+#define DEF_SAT_S_TRUNC_FMT_7(NT, WT, NT_MIN, NT_MAX) \
+NT __attribute__((noinline)) \
+sat_s_trunc_##WT##_to_##NT##_fmt_7 (WT x) \
+{ \
+ NT trunc = (NT)x; \
+ return (WT)NT_MIN >= x || x >= (WT)NT_MAX \
+ ? x < 0 ? NT_MIN : NT_MAX \
+ : trunc; \
+}
+#define DEF_SAT_S_TRUNC_FMT_7_WRAP(NT, WT, NT_MIN, NT_MAX) \
+ DEF_SAT_S_TRUNC_FMT_7(NT, WT, NT_MIN, NT_MAX)
+
+#define DEF_SAT_S_TRUNC_FMT_8(NT, WT, NT_MIN, NT_MAX) \
+NT __attribute__((noinline)) \
+sat_s_trunc_##WT##_to_##NT##_fmt_8 (WT x) \
+{ \
+ NT trunc = (NT)x; \
+ return (WT)NT_MIN > x || x >= (WT)NT_MAX \
+ ? x < 0 ? NT_MIN : NT_MAX \
+ : trunc; \
+}
+#define DEF_SAT_S_TRUNC_FMT_8_WRAP(NT, WT, NT_MIN, NT_MAX) \
+ DEF_SAT_S_TRUNC_FMT_8(NT, WT, NT_MIN, NT_MAX)
+
+#define RUN_SAT_S_TRUNC_FMT_1(NT, WT, x) sat_s_trunc_##WT##_to_##NT##_fmt_1 (x)
+#define RUN_SAT_S_TRUNC_FMT_1_WRAP(NT, WT, x) RUN_SAT_S_TRUNC_FMT_1(NT, WT, x)
+
+#define RUN_SAT_S_TRUNC_FMT_2(NT, WT, x) sat_s_trunc_##WT##_to_##NT##_fmt_2 (x)
+#define RUN_SAT_S_TRUNC_FMT_2_WRAP(NT, WT, x) RUN_SAT_S_TRUNC_FMT_2(NT, WT, x)
+
+#define RUN_SAT_S_TRUNC_FMT_3(NT, WT, x) sat_s_trunc_##WT##_to_##NT##_fmt_3 (x)
+#define RUN_SAT_S_TRUNC_FMT_3_WRAP(NT, WT, x) RUN_SAT_S_TRUNC_FMT_3(NT, WT, x)
+
+#define RUN_SAT_S_TRUNC_FMT_4(NT, WT, x) sat_s_trunc_##WT##_to_##NT##_fmt_4 (x)
+#define RUN_SAT_S_TRUNC_FMT_4_WRAP(NT, WT, x) RUN_SAT_S_TRUNC_FMT_4(NT, WT, x)
+
+#define RUN_SAT_S_TRUNC_FMT_5(NT, WT, x) sat_s_trunc_##WT##_to_##NT##_fmt_5 (x)
+#define RUN_SAT_S_TRUNC_FMT_5_WRAP(NT, WT, x) RUN_SAT_S_TRUNC_FMT_5(NT, WT, x)
+
+#define RUN_SAT_S_TRUNC_FMT_6(NT, WT, x) sat_s_trunc_##WT##_to_##NT##_fmt_6 (x)
+#define RUN_SAT_S_TRUNC_FMT_6_WRAP(NT, WT, x) RUN_SAT_S_TRUNC_FMT_6(NT, WT, x)
+
+#define RUN_SAT_S_TRUNC_FMT_7(NT, WT, x) sat_s_trunc_##WT##_to_##NT##_fmt_7 (x)
+#define RUN_SAT_S_TRUNC_FMT_7_WRAP(NT, WT, x) RUN_SAT_S_TRUNC_FMT_7(NT, WT, x)
+
+#define RUN_SAT_S_TRUNC_FMT_8(NT, WT, x) sat_s_trunc_##WT##_to_##NT##_fmt_8 (x)
+#define RUN_SAT_S_TRUNC_FMT_8_WRAP(NT, WT, x) RUN_SAT_S_TRUNC_FMT_8(NT, WT, x)
+
+#endif
--- /dev/null
+#ifndef HAVE_DEFINED_SAT_ARITH_DATA_H
+#define HAVE_DEFINED_SAT_ARITH_DATA_H
+
+#define TEST_UNARY_STRUCT_NAME(T1, T2) test_##T1##_##T2##_s
+#define TEST_UNARY_STRUCT_DECL(T1, T2) struct TEST_UNARY_STRUCT_NAME(T1, T2)
+#define TEST_UNARY_STRUCT(T1, T2) \
+ struct TEST_UNARY_STRUCT_NAME(T1, T2) \
+ { \
+ T1 to; \
+ T2 from; \
+ };
+
+#define TEST_BINARY_STRUCT_NAME(T, NAME) test_##T##_##NAME##_s
+#define TEST_BINARY_STRUCT_DECL(T, NAME) struct TEST_BINARY_STRUCT_NAME(T, NAME)
+#define TEST_BINARY_STRUCT(T, NAME) \
+ struct TEST_BINARY_STRUCT_NAME(T, NAME) \
+ { \
+ T a, b; \
+ T expect; \
+ };
+
+#define TEST_UNARY_DATA(T1, T2) t_##T1##_##T2##_s
+#define TEST_UNARY_DATA_WRAP(T1, T2) TEST_UNARY_DATA(T1, T2)
+
+#define TEST_BINARY_DATA(T, NAME) t_##T##_##NAME##_s
+#define TEST_BINARY_DATA_WRAP(T, NAME) TEST_BINARY_DATA(T, NAME)
+
+TEST_UNARY_STRUCT (uint8_t, uint16_t)
+TEST_UNARY_STRUCT (uint8_t, uint32_t)
+TEST_UNARY_STRUCT (uint8_t, uint64_t)
+TEST_UNARY_STRUCT (uint16_t, uint32_t)
+TEST_UNARY_STRUCT (uint16_t, uint64_t)
+TEST_UNARY_STRUCT (uint32_t, uint64_t)
+
+TEST_BINARY_STRUCT (int8_t, ssadd)
+TEST_BINARY_STRUCT (int16_t, ssadd)
+TEST_BINARY_STRUCT (int32_t, ssadd)
+TEST_BINARY_STRUCT (int64_t, ssadd)
+
+TEST_BINARY_STRUCT (int8_t, sssub)
+TEST_BINARY_STRUCT (int16_t, sssub)
+TEST_BINARY_STRUCT (int32_t, sssub)
+TEST_BINARY_STRUCT (int64_t, sssub)
+
+TEST_UNARY_STRUCT (int8_t, int16_t)
+TEST_UNARY_STRUCT (int8_t, int32_t)
+TEST_UNARY_STRUCT (int8_t, int64_t)
+TEST_UNARY_STRUCT (int16_t, int32_t)
+TEST_UNARY_STRUCT (int16_t, int64_t)
+TEST_UNARY_STRUCT (int32_t, int64_t)
+
+TEST_UNARY_STRUCT_DECL(uint8_t, uint16_t) \
+ TEST_UNARY_DATA(uint8_t, uint16_t)[] =
+{
+ { 0, 0},
+ { 2, 2},
+ {254, 254},
+ {255, 255},
+ {255, 256},
+ {255, 65534},
+ {255, 65535},
+};
+
+TEST_UNARY_STRUCT_DECL(uint8_t, uint32_t) \
+ TEST_UNARY_DATA(uint8_t, uint32_t)[] =
+{
+ { 0, 0},
+ { 2, 2},
+ {254, 254},
+ {255, 255},
+ {255, 256},
+ {255, 65534},
+ {255, 65535},
+ {255, 65536},
+ {255, 4294967294},
+ {255, 4294967295},
+};
+
+TEST_UNARY_STRUCT_DECL(uint8_t, uint64_t) \
+ TEST_UNARY_DATA(uint8_t, uint64_t)[] =
+{
+ { 0, 0},
+ { 2, 2},
+ {254, 254},
+ {255, 255},
+ {255, 256},
+ {255, 65534},
+ {255, 65535},
+ {255, 65536},
+ {255, 4294967294},
+ {255, 4294967295},
+ {255, 4294967296},
+ {255, 18446744073709551614u},
+ {255, 18446744073709551615u},
+};
+
+TEST_UNARY_STRUCT_DECL(uint16_t, uint32_t) \
+ TEST_UNARY_DATA(uint16_t, uint32_t)[] =
+{
+ { 0, 0},
+ { 5, 5},
+ {65534, 65534},
+ {65535, 65535},
+ {65535, 65536},
+ {65535, 4294967294},
+ {65535, 4294967295},
+};
+
+TEST_UNARY_STRUCT_DECL(uint16_t, uint64_t) \
+ TEST_UNARY_DATA(uint16_t, uint64_t)[] =
+{
+ { 0, 0},
+ { 5, 5},
+ {65534, 65534},
+ {65535, 65535},
+ {65535, 65536},
+ {65535, 4294967294},
+ {65535, 4294967295},
+ {65535, 4294967296},
+ {65535, 18446744073709551614u},
+ {65535, 18446744073709551615u},
+};
+
+TEST_UNARY_STRUCT_DECL(uint32_t, uint64_t) \
+ TEST_UNARY_DATA(uint32_t, uint64_t)[] =
+{
+ { 0, 0},
+ { 9, 9},
+ {4294967294, 4294967294},
+ {4294967295, 4294967295},
+ {4294967295, 4294967296},
+ {4294967295, 18446744073709551614u},
+ {4294967295, 18446744073709551615u},
+};
+
+TEST_UNARY_STRUCT_DECL(int8_t, int16_t) \
+ TEST_UNARY_DATA(int8_t, int16_t)[] =
+{
+ { 0, 0},
+ { -2, -2},
+ { 127, 128},
+ { 127, 258},
+ {-128, -128},
+ {-128, -129},
+ {-128, -257},
+ { 127, 32767},
+ {-128, -32768},
+};
+
+TEST_UNARY_STRUCT_DECL(int8_t, int32_t) \
+ TEST_UNARY_DATA(int8_t, int32_t)[] =
+{
+ { 0, 0},
+ { -2, -2},
+ { 127, 128},
+ { 127, 258},
+ {-128, -128},
+ {-128, -129},
+ {-128, -257},
+ { 127, 32767},
+ {-128, -32768},
+ { 127, 65536},
+ {-128, -65537},
+ { 127, 2147483647},
+ {-128, -2147483648},
+};
+
+TEST_UNARY_STRUCT_DECL(int8_t, int64_t) \
+ TEST_UNARY_DATA(int8_t, int64_t)[] =
+{
+ { 0, 0},
+ { -2, -2},
+ { 127, 128},
+ { 127, 258},
+ {-128, -128},
+ {-128, -129},
+ {-128, -257},
+ { 127, 32767},
+ {-128, -32768},
+ { 127, 65536},
+ {-128, -65537},
+ { 127, 2147483647},
+ {-128, -2147483648},
+ { 127, 2147483648ll},
+ {-128, -2147483649ll},
+ { 127, 9223372036854775807ll},
+ {-128, -9223372036854775808ull},
+};
+
+TEST_UNARY_STRUCT_DECL(int16_t, int32_t) \
+ TEST_UNARY_DATA(int16_t, int32_t)[] =
+{
+ { 0, 0},
+ { -2, -2},
+ { 32767, 32768},
+ { 32767, 65538},
+ {-32768, -32768},
+ {-32768, -32769},
+ {-32768, -65539},
+ { 32767, 32767},
+ {-32768, -32768},
+ { 32767, 65536},
+ {-32768, -65537},
+ { 32767, 2147483647},
+ {-32768, -2147483648},
+};
+
+TEST_UNARY_STRUCT_DECL(int16_t, int64_t) \
+ TEST_UNARY_DATA(int16_t, int64_t)[] =
+{
+ { 0, 0},
+ { -2, -2},
+ { 32767, 32768},
+ { 32767, 65538},
+ {-32768, -32768},
+ {-32768, -32769},
+ {-32768, -65539},
+ { 32767, 32767},
+ {-32768, -32768},
+ { 32767, 65536},
+ {-32768, -65537},
+ { 32767, 2147483647},
+ {-32768, -2147483648},
+};
+
+TEST_UNARY_STRUCT_DECL(int32_t, int64_t) \
+ TEST_UNARY_DATA(int32_t, int64_t)[] =
+{
+ { 0, 0},
+ { -2, -2},
+ { 2147483647, 2147483648ll},
+ {-2147483648, -2147483648},
+ { 2147483647, 2147483648},
+ {-2147483648, -2147483649ll},
+ { 2147483647, 9223372036854775807ll},
+ {-2147483648, -9223372036854775808ull},
+};
+
+TEST_BINARY_STRUCT_DECL(int8_t, ssadd) TEST_BINARY_DATA(int8_t, ssadd)[] =
+{
+ { 0, 0, 0},
+ { 2, 2, 4},
+ { 126, 1, 127},
+ { 127, 1, 127},
+ { 127, 127, 127},
+ { -7, -4, -11},
+ {-128, -1, -128},
+ {-127, -1, -128},
+ {-128, -128, -128},
+ {-128, 127, -1},
+ {-127, 127, 0},
+ {-122, 105, -17},
+ {-122, 125, 3},
+};
+
+TEST_BINARY_STRUCT_DECL(int16_t, ssadd) TEST_BINARY_DATA(int16_t, ssadd)[] =
+{
+ { 0, 0, 0},
+ { 2, 2, 4},
+ { 32766, 1, 32767},
+ { 32767, 1, 32767},
+ { 32767, 32767, 32767},
+ { -7, -4, -11},
+ {-32768, -1, -32768},
+ {-32767, -1, -32768},
+ {-32768, -32768, -32768},
+ {-32768, 32767, -1},
+ {-32767, 32767, 0},
+ {-32732, 32712, -20},
+ {-32732, 32734, 2},
+};
+
+TEST_BINARY_STRUCT_DECL(int32_t, ssadd) TEST_BINARY_DATA(int32_t, ssadd)[] =
+{
+ { 0, 0, 0},
+ { 2, 2, 4},
+ { 2147483646, 1, 2147483647},
+ { 2147483647, 1, 2147483647},
+ { 2147483647, 2147483647, 2147483647},
+ { -7, -4, -11},
+ {-2147483648, -1, -2147483648},
+ {-2147483647, -1, -2147483648},
+ {-2147483648, -2147483648, -2147483648},
+ {-2147483648, 2147483647, -1},
+ {-2147483647, 2147483647, 0},
+ {-2147483613, 2147483601, -12},
+ {-2147483613, 2147483637, 24},
+};
+
+TEST_BINARY_STRUCT_DECL(int64_t, ssadd) TEST_BINARY_DATA(int64_t, ssadd)[] =
+{
+ { 0, 0, 0},
+ { 2, 2, 4},
+ { 9223372036854775806ll, 1, 9223372036854775807ll},
+ { 9223372036854775807ll, 1, 9223372036854775807ll},
+ { 9223372036854775807ll, 9223372036854775807ll, 9223372036854775807ll},
+ { -7, -4, -11},
+ {-9223372036854775808ull, -1, -9223372036854775808ull},
+ { -9223372036854775807ll, -1, -9223372036854775808ull},
+ {-9223372036854775808ull, -9223372036854775808ull, -9223372036854775808ull},
+ {-9223372036854775808ull, 9223372036854775807ll, -1},
+ { -9223372036854775807ll, 9223372036854775807ll, 0},
+ { -9223372036854775803ll, 9223372036854775800ll, -3},
+ { -9223372036854775803ll, 9223372036854775805ll, 2},
+};
+
+TEST_BINARY_STRUCT_DECL(int8_t, sssub) TEST_BINARY_DATA(int8_t, sssub)[] =
+{
+ { 0, 0, 0},
+ { 2, 4, -2},
+ { 126, -1, 127},
+ { 127, -1, 127},
+ { 127, -127, 127},
+ { -7, -4, -3},
+ {-127, 1, -128},
+ {-128, 1, -128},
+ {-128, 127, -128},
+ {-128, -127, -1},
+ {-124, -127, 3},
+ {-125, -120, -5},
+ { 126, 120, 6},
+};
+
+TEST_BINARY_STRUCT_DECL(int16_t, sssub) TEST_BINARY_DATA(int16_t, sssub)[] =
+{
+ { 0, 0, 0},
+ { 2, 4, -2},
+ { 32766, -1, 32767},
+ { 32767, -1, 32767},
+ { 32767, -32767, 32767},
+ { -7, -4, -3},
+ {-32767, 1, -32768},
+ {-32768, 1, -32768},
+ {-32768, 32767, -32768},
+ {-32768, -32767, -1},
+ {-32764, -32767, 3},
+ {-32765, -32760, -5},
+ { 32766, 32760, 6},
+};
+
+TEST_BINARY_STRUCT_DECL(int32_t, sssub) TEST_BINARY_DATA(int32_t, sssub)[] =
+{
+ { 0, 0, 0},
+ { 2, 4, -2},
+ { 2147483646, -1, 2147483647},
+ { 2147483647, -1, 2147483647},
+ { 2147483647, -2147483647, 2147483647},
+ { -7, -4, -3},
+ {-2147483647, 1, -2147483648},
+ {-2147483648, 1, -2147483648},
+ {-2147483648, 2147483647, -2147483648},
+ {-2147483648, -2147483647, -1},
+ {-2147483644, -2147483647, 3},
+ {-2147483645, -2147483640, -5},
+ { 2147483646, 2147483640, 6},
+};
+
+TEST_BINARY_STRUCT_DECL(int64_t, sssub) TEST_BINARY_DATA(int64_t, sssub)[] =
+{
+ { 0, 0, 0},
+ { 2, 4, -2},
+ { 9223372036854775806ll, -1, 9223372036854775807ll},
+ { 9223372036854775807ll, -1, 9223372036854775807ll},
+ { 9223372036854775807ll, -9223372036854775807ll, 9223372036854775807ll},
+ { -7, -4, -3},
+ { -9223372036854775807ll, 1, -9223372036854775808ull},
+ {-9223372036854775808ull, 1, -9223372036854775808ull},
+ {-9223372036854775808ull, 9223372036854775807ll, -9223372036854775808ull},
+ {-9223372036854775808ull, -9223372036854775807ll, -1},
+ { -9223372036854775804ll, -9223372036854775807ll, 3},
+ { -9223372036854775805ll, -9223372036854775800ll, -5},
+ { 9223372036854775806ll, 9223372036854775800ll, 6},
+};
+
+#endif