@@ -353,6 +353,23 @@ 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 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)
+
/******************************************************************************/
/* Saturation Truncate (unsigned and signed) */
/******************************************************************************/
@@ -37,6 +37,11 @@ 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_DECL(uint8_t, uint16_t) \
TEST_UNARY_DATA(uint8_t, uint16_t)[] =
{
@@ -189,4 +194,72 @@ TEST_BINARY_STRUCT_DECL(int64_t, ssadd) TEST_BINARY_DATA(int64_t, ssadd)[] =
{ -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
new file mode 100644
@@ -0,0 +1,30 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "sat_arith.h"
+
+/*
+** sat_s_sub_int16_t_fmt_1:
+** sub\s+[atx][0-9]+,\s*a0,\s*a1
+** xor\s+[atx][0-9]+,\s*a0,\s*a1
+** xor\s+[atx][0-9]+,\s*a0,\s*[atx][0-9]+
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*15
+** andi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** srai\s+[atx][0-9]+,\s*[atx][0-9]+,\s*63
+** li\s+[atx][0-9]+,\s*32768
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** xor\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** neg\s+[atx][0-9]+,\s*[atx][0-9]+
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** or\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** slliw\s+a0,\s*a0,\s*16
+** sraiw\s+a0,\s*a0,\s*16
+** ret
+*/
+DEF_SAT_S_SUB_FMT_1(int16_t, uint16_t, INT16_MIN, INT16_MAX)
+
+/* { dg-final { scan-rtl-dump-times ".SAT_SUB " 2 "expand" } } */
new file mode 100644
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "sat_arith.h"
+
+/*
+** sat_s_sub_int32_t_fmt_1:
+** sub\s+[atx][0-9]+,\s*a0,\s*a1
+** xor\s+[atx][0-9]+,\s*a0,\s*a1
+** xor\s+[atx][0-9]+,\s*a0,\s*[atx][0-9]+
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** srliw\s+[atx][0-9]+,\s*[atx][0-9]+,\s*31
+** srai\s+[atx][0-9]+,\s*[atx][0-9]+,\s*63
+** li\s+[atx][0-9]+,\s*-2147483648
+** xori\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** xor\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-7]
+** neg\s+[atx][0-9]+,\s*[atx][0-9]+
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** or\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** sext\.w\s+a0,\s*[atx][0-9]+
+** ret
+*/
+DEF_SAT_S_SUB_FMT_1(int32_t, uint32_t, INT32_MIN, INT32_MAX)
+
+/* { dg-final { scan-rtl-dump-times ".SAT_SUB " 2 "expand" } } */
new file mode 100644
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "sat_arith.h"
+
+/*
+** sat_s_sub_int64_t_fmt_1:
+** sub\s+[atx][0-9]+,\s*a0,\s*a1
+** xor\s+[atx][0-9]+,\s*a0,\s*a1
+** xor\s+[atx][0-9]+,\s*a0,\s*[atx][0-9]+
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*63
+** srai\s+[atx][0-9]+,\s*[atx][0-9]+,\s*63
+** li\s+[atx][0-9]+,\s*-1
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** xor\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** neg\s+[atx][0-9]+,\s*[atx][0-9]+
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** or\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** ret
+*/
+DEF_SAT_S_SUB_FMT_1(int64_t, uint64_t, INT64_MIN, INT64_MAX)
+
+/* { dg-final { scan-rtl-dump-times ".SAT_SUB " 2 "expand" } } */
new file mode 100644
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-march=rv64gc -mabi=lp64d -O3 -fdump-rtl-expand-details -fno-schedule-insns -fno-schedule-insns2" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include "sat_arith.h"
+
+/*
+** sat_s_sub_int8_t_fmt_1:
+** sub\s+[atx][0-9]+,\s*a0,\s*a1
+** xor\s+[atx][0-9]+,\s*a0,\s*a1
+** xor\s+[atx][0-9]+,\s*a0,\s*[atx][0-9]+
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** srli\s+[atx][0-9]+,\s*[atx][0-9]+,\s*7
+** andi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*1
+** srai\s+[atx][0-9]+,\s*[atx][0-9]+,\s*63
+** xori\s+[atx][0-9]+,\s*[atx][0-9]+,\s*127
+** neg\s+[atx][0-9]+,\s*[atx][0-9]+
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** addi\s+[atx][0-9]+,\s*[atx][0-9]+,\s*-1
+** and\s+[atx][0-9]+,\s*[atx][0-9]+,\s*[atx][0-9]+
+** or\s+a0,\s*[atx][0-9]+,\s*[atx][0-9]+
+** slliw\s+a0,\s*a0,\s*24
+** sraiw\s+a0,\s*a0,\s*24
+** ret
+*/
+DEF_SAT_S_SUB_FMT_1(int8_t, uint8_t, INT8_MIN, INT8_MAX)
+
+/* { dg-final { scan-rtl-dump-times ".SAT_SUB " 2 "expand" } } */
new file mode 100644
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+#include "sat_arith_data.h"
+
+#define T1 int16_t
+#define T2 uint16_t
+
+DEF_SAT_S_SUB_FMT_1_WRAP(T1, T2, INT16_MIN, INT16_MAX)
+
+#define DATA TEST_BINARY_DATA_WRAP(T1, sssub)
+#define T TEST_BINARY_STRUCT_DECL(T1, sssub)
+#define RUN_BINARY(x, y) RUN_SAT_S_SUB_FMT_1_WRAP(T1, x, y)
+
+#include "scalar_sat_binary_run_xxx.h"
new file mode 100644
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+#include "sat_arith_data.h"
+
+#define T1 int32_t
+#define T2 uint32_t
+
+DEF_SAT_S_SUB_FMT_1_WRAP(T1, T2, INT32_MIN, INT32_MAX)
+
+#define DATA TEST_BINARY_DATA_WRAP(T1, sssub)
+#define T TEST_BINARY_STRUCT_DECL(T1, sssub)
+#define RUN_BINARY(x, y) RUN_SAT_S_SUB_FMT_1_WRAP(T1, x, y)
+
+#include "scalar_sat_binary_run_xxx.h"
new file mode 100644
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+#include "sat_arith_data.h"
+
+#define T1 int64_t
+#define T2 uint64_t
+
+DEF_SAT_S_SUB_FMT_1_WRAP(T1, T2, INT64_MIN, INT64_MAX)
+
+#define DATA TEST_BINARY_DATA_WRAP(T1, sssub)
+#define T TEST_BINARY_STRUCT_DECL(T1, sssub)
+#define RUN_BINARY(x, y) RUN_SAT_S_SUB_FMT_1_WRAP(T1, x, y)
+
+#include "scalar_sat_binary_run_xxx.h"
new file mode 100644
@@ -0,0 +1,16 @@
+/* { dg-do run { target { riscv_v } } } */
+/* { dg-additional-options "-std=c99" } */
+
+#include "sat_arith.h"
+#include "sat_arith_data.h"
+
+#define T1 int8_t
+#define T2 uint8_t
+
+DEF_SAT_S_SUB_FMT_1_WRAP(T1, T2, INT8_MIN, INT8_MAX)
+
+#define DATA TEST_BINARY_DATA_WRAP(T1, sssub)
+#define T TEST_BINARY_STRUCT_DECL(T1, sssub)
+#define RUN_BINARY(x, y) RUN_SAT_S_SUB_FMT_1_WRAP(T1, x, y)
+
+#include "scalar_sat_binary_run_xxx.h"