All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Hexagon (target/hexagon) add overrides for S2_asr_r_r_sat/S2_asl_r_r_sat
@ 2022-05-09 21:14 Taylor Simpson
  2022-05-09 21:14 ` [PATCH] Hexagon (target/hexagon) make VyV operands use a unique temp Taylor Simpson
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: Taylor Simpson @ 2022-05-09 21:14 UTC (permalink / raw)
  To: qemu-devel; +Cc: tsimpson, richard.henderson, f4bug, ale, bcain, mlambert

These instructions will not be generated by idef-parser, so we override
them manually.

Test cases added to tests/tcg/hexagon/usr.c

Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
---
 target/hexagon/gen_tcg.h |  10 ++-
 target/hexagon/genptr.c  | 147 +++++++++++++++++++++++++++++++++++++++
 tests/tcg/hexagon/usr.c  |  22 ++++--
 3 files changed, 172 insertions(+), 7 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index c6f0879b6e..9268f49acd 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -610,6 +610,14 @@
         tcg_temp_free(tmp); \
     } while (0)
 
+/* r0 = asr(r1, r2):sat */
+#define fGEN_TCG_S2_asr_r_r_sat(SHORTCODE) \
+    gen_asr_r_r_sat(RdV, RsV, RtV)
+
+/* r0 = asl(r1, r2):sat */
+#define fGEN_TCG_S2_asl_r_r_sat(SHORTCODE) \
+    gen_asl_r_r_sat(RdV, RsV, RtV)
+
 /* Floating point */
 #define fGEN_TCG_F2_conv_sf2df(SHORTCODE) \
     gen_helper_conv_sf2df(RddV, cpu_env, RsV)
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index cd6af4bceb..36e6451859 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -468,6 +468,153 @@ static TCGv gen_8bitsof(TCGv result, TCGv value)
     return result;
 }
 
+static void gen_set_usr_field(int field, TCGv val)
+{
+    tcg_gen_deposit_tl(hex_new_value[HEX_REG_USR], hex_new_value[HEX_REG_USR],
+                       val,
+                       reg_field_info[field].offset,
+                       reg_field_info[field].width);
+}
+
+static void gen_set_usr_fieldi(int field, int x)
+{
+    TCGv val = tcg_const_tl(x);
+    gen_set_usr_field(field, val);
+    tcg_temp_free(val);
+}
+
+static void gen_sat_i64(TCGv_i64 dst, TCGv_i64 src, uint32_t bits)
+{
+    TCGLabel *label = gen_new_label();
+
+    tcg_gen_sextract_i64(dst, src, 0, bits);
+    tcg_gen_brcond_i64(TCG_COND_EQ, dst, src, label);
+    {
+        TCGv_i64 min = tcg_constant_i64(-(1LL << (bits - 1)));
+        TCGv_i64 max = tcg_constant_i64((1LL << (bits - 1)) - 1);
+        tcg_gen_movcond_i64(TCG_COND_LT, dst, src, tcg_constant_i64(0),
+                            min, max);
+        gen_set_usr_fieldi(USR_OVF, 1);
+    }
+    gen_set_label(label);
+}
+
+static void gen_satval(TCGv_i64 dest, TCGv_i64 source, uint32_t bits)
+{
+    TCGv_i64 min = tcg_constant_i64(-(1LL << (bits - 1)));
+    TCGv_i64 max = tcg_constant_i64((1LL << (bits - 1)) - 1);
+
+    gen_set_usr_fieldi(USR_OVF, 1);
+    tcg_gen_movcond_i64(TCG_COND_LT, dest, source, tcg_constant_i64(0),
+                        min, max);
+}
+
+/* Shift left with saturation */
+static void gen_shl_sat(TCGv RdV, TCGv RsV, TCGv shift_amt)
+{
+    /*
+     * int64_t A = (fCAST4_8s(RsV) << shift_amt;
+     * if (((int32_t)((fSAT(A)) ^ ((int32_t)(RsV)))) < 0) {
+     *     RdV = fSATVALN(32, ((int32_t)(RsV)))
+     * } else if (((RsV) > 0) && ((A) == 0)) {
+     *     RdV = fSATVALN(32, (RsV));
+     * } else {
+     *     RdV = fSAT(A);
+     * }
+     */
+    TCGv_i64 RsV_i64 = tcg_temp_local_new_i64();
+    TCGv_i64 shift_amt_i64 = tcg_temp_local_new_i64();
+    TCGv_i64 A = tcg_temp_local_new_i64();
+    TCGv_i64 A_sat_i64 = tcg_temp_local_new_i64();
+    TCGv A_sat = tcg_temp_local_new();
+    TCGv_i64 RdV_i64 = tcg_temp_local_new_i64();
+    TCGv tmp = tcg_temp_new();
+    TCGLabel *label1 = gen_new_label();
+    TCGLabel *label2 = gen_new_label();
+    TCGLabel *done = gen_new_label();
+
+    tcg_gen_ext_i32_i64(RsV_i64, RsV);
+    tcg_gen_ext_i32_i64(shift_amt_i64, shift_amt);
+    tcg_gen_shl_i64(A, RsV_i64, shift_amt_i64);
+
+    /* Check for saturation */
+    gen_sat_i64(A_sat_i64, A, 32);
+    tcg_gen_extrl_i64_i32(A_sat, A_sat_i64);
+    tcg_gen_xor_tl(tmp, A_sat, RsV);
+    tcg_gen_brcondi_tl(TCG_COND_GE, tmp, 0, label1);
+    gen_satval(RdV_i64, RsV_i64, 32);
+    tcg_gen_extrl_i64_i32(RdV, RdV_i64);
+    tcg_gen_br(done);
+
+    gen_set_label(label1);
+    tcg_gen_brcondi_tl(TCG_COND_LE, RsV, 0, label2);
+    tcg_gen_brcondi_i64(TCG_COND_NE, A, 0, label2);
+    gen_satval(RdV_i64, RsV_i64, 32);
+    tcg_gen_extrl_i64_i32(RdV, RdV_i64);
+    tcg_gen_br(done);
+
+    gen_set_label(label2);
+    tcg_gen_mov_tl(RdV, A_sat);
+
+    gen_set_label(done);
+
+    tcg_temp_free_i64(RsV_i64);
+    tcg_temp_free_i64(shift_amt_i64);
+    tcg_temp_free_i64(A);
+    tcg_temp_free_i64(A_sat_i64);
+    tcg_temp_free(A_sat);
+    tcg_temp_free_i64(RdV_i64);
+    tcg_temp_free(tmp);
+}
+
+/* Bidirectional shift right with saturation */
+static void gen_asr_r_r_sat(TCGv RdV, TCGv RsV, TCGv RtV)
+{
+    TCGv shift_amt = tcg_temp_local_new();
+    TCGLabel *positive = gen_new_label();
+    TCGLabel *done = gen_new_label();
+
+    tcg_gen_sextract_i32(shift_amt, RtV, 0, 7);
+    tcg_gen_brcondi_tl(TCG_COND_GE, shift_amt, 0, positive);
+
+    /* Negative shift amount => shift left */
+    tcg_gen_neg_tl(shift_amt, shift_amt);
+    gen_shl_sat(RdV, RsV, shift_amt);
+    tcg_gen_br(done);
+
+    gen_set_label(positive);
+    /* Positive shift amount => shift right */
+    tcg_gen_sar_tl(RdV, RsV, shift_amt);
+
+    gen_set_label(done);
+
+    tcg_temp_free(shift_amt);
+}
+
+/* Bidirectional shift left with saturation */
+static void gen_asl_r_r_sat(TCGv RdV, TCGv RsV, TCGv RtV)
+{
+    TCGv shift_amt = tcg_temp_local_new();
+    TCGLabel *positive = gen_new_label();
+    TCGLabel *done = gen_new_label();
+
+    tcg_gen_sextract_i32(shift_amt, RtV, 0, 7);
+    tcg_gen_brcondi_tl(TCG_COND_GE, shift_amt, 0, positive);
+
+    /* Negative shift amount => shift right */
+    tcg_gen_neg_tl(shift_amt, shift_amt);
+    tcg_gen_sar_tl(RdV, RsV, shift_amt);
+    tcg_gen_br(done);
+
+    gen_set_label(positive);
+    /* Positive shift amount => shift left */
+    gen_shl_sat(RdV, RsV, shift_amt);
+
+    gen_set_label(done);
+
+    tcg_temp_free(shift_amt);
+}
+
 static intptr_t vreg_src_off(DisasContext *ctx, int num)
 {
     intptr_t offset = offsetof(CPUHexagonState, VRegs[num]);
diff --git a/tests/tcg/hexagon/usr.c b/tests/tcg/hexagon/usr.c
index a531511cec..e32c5e32a8 100644
--- a/tests/tcg/hexagon/usr.c
+++ b/tests/tcg/hexagon/usr.c
@@ -427,6 +427,7 @@ FUNC_P_OP_P(vabshsat,           "%0 = vabsh(%2):sat")
 FUNC_P_OP_PP(vnavgwr,           "%0 = vnavgw(%2, %3):rnd:sat")
 FUNC_R_OP_RI(round_ri_sat,      "%0 = round(%2, #%3):sat")
 FUNC_R_OP_RR(asr_r_r_sat,       "%0 = asr(%2, %3):sat")
+FUNC_R_OP_RR(asl_r_r_sat,       "%0 = asl(%2, %3):sat")
 
 FUNC_XPp_OP_PP(ACS,             "%0, p2 = vacsh(%3, %4)")
 
@@ -905,12 +906,21 @@ int main()
     TEST_R_OP_RI(round_ri_sat,         0x0000ffff, 2, 0x00004000, USR_CLEAR);
     TEST_R_OP_RI(round_ri_sat,         0x7fffffff, 2, 0x1fffffff, USR_OVF);
 
-    TEST_R_OP_RR(asr_r_r_sat,          0x0000ffff, 0x00000002, 0x00003fff,
-                 USR_CLEAR);
-    TEST_R_OP_RR(asr_r_r_sat,          0x00ffffff, 0xfffffff5, 0x7fffffff,
-                 USR_OVF);
-    TEST_R_OP_RR(asr_r_r_sat,          0x80000000, 0xfffffff5, 0x80000000,
-                 USR_OVF);
+    TEST_R_OP_RR(asr_r_r_sat,  0x0000ffff, 0x02, 0x00003fff, USR_CLEAR);
+    TEST_R_OP_RR(asr_r_r_sat,  0x80000000, 0x01, 0xc0000000, USR_CLEAR);
+    TEST_R_OP_RR(asr_r_r_sat,  0xffffffff, 0x01, 0xffffffff, USR_CLEAR);
+    TEST_R_OP_RR(asr_r_r_sat,  0x00ffffff, 0xf5, 0x7fffffff, USR_OVF);
+    TEST_R_OP_RR(asr_r_r_sat,  0x80000000, 0xf5, 0x80000000, USR_OVF);
+    TEST_R_OP_RR(asr_r_r_sat,  0x7fff0000, 0x42, 0x7fffffff, USR_OVF);
+    TEST_R_OP_RR(asr_r_r_sat,  0xff000000, 0x42, 0x80000000, USR_OVF);
+
+    TEST_R_OP_RR(asl_r_r_sat,  0x00000000, 0x40, 0x00000000, USR_CLEAR);
+    TEST_R_OP_RR(asl_r_r_sat,  0x80000000, 0xff, 0xc0000000, USR_CLEAR);
+    TEST_R_OP_RR(asl_r_r_sat,  0xffffffff, 0xff, 0xffffffff, USR_CLEAR);
+    TEST_R_OP_RR(asl_r_r_sat,  0x00ffffff, 0x0b, 0x7fffffff, USR_OVF);
+    TEST_R_OP_RR(asl_r_r_sat,  0x80000000, 0x0b, 0x80000000, USR_OVF);
+    TEST_R_OP_RR(asl_r_r_sat,  0x7fff0000, 0xbe, 0x7fffffff, USR_OVF);
+    TEST_R_OP_RR(asl_r_r_sat,  0xff000000, 0xbe, 0x80000000, USR_OVF);
 
     TEST_XPp_OP_PP(ACS, 0x0004000300020001ULL, 0x0001000200030004ULL,
                    0x0000000000000000ULL, 0x0004000300030004ULL, 0xf0,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread
* [PATCH] Hexagon (target/hexagon) add overrides for S2_asr_r_r_sat/S2_asl_r_r_sat
@ 2022-06-06 22:23 Taylor Simpson
  2022-06-06 22:23 ` [PATCH] Hexagon (target/hexagon) remove unused encodings Taylor Simpson
  0 siblings, 1 reply; 11+ messages in thread
From: Taylor Simpson @ 2022-06-06 22:23 UTC (permalink / raw)
  To: qemu-devel; +Cc: tsimpson, richard.henderson, f4bug, ale, bcain, mlambert

These instructions will not be generated by idef-parser, so we override
them manually.

Test cases added to tests/tcg/hexagon/usr.c

Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
---
 target/hexagon/gen_tcg.h |  10 ++-
 target/hexagon/genptr.c  | 147 +++++++++++++++++++++++++++++++++++++++
 tests/tcg/hexagon/usr.c  |  22 ++++--
 3 files changed, 172 insertions(+), 7 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index c6f0879b6e..9268f49acd 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -610,6 +610,14 @@
         tcg_temp_free(tmp); \
     } while (0)
 
+/* r0 = asr(r1, r2):sat */
+#define fGEN_TCG_S2_asr_r_r_sat(SHORTCODE) \
+    gen_asr_r_r_sat(RdV, RsV, RtV)
+
+/* r0 = asl(r1, r2):sat */
+#define fGEN_TCG_S2_asl_r_r_sat(SHORTCODE) \
+    gen_asl_r_r_sat(RdV, RsV, RtV)
+
 /* Floating point */
 #define fGEN_TCG_F2_conv_sf2df(SHORTCODE) \
     gen_helper_conv_sf2df(RddV, cpu_env, RsV)
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index cd6af4bceb..36e6451859 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -468,6 +468,153 @@ static TCGv gen_8bitsof(TCGv result, TCGv value)
     return result;
 }
 
+static void gen_set_usr_field(int field, TCGv val)
+{
+    tcg_gen_deposit_tl(hex_new_value[HEX_REG_USR], hex_new_value[HEX_REG_USR],
+                       val,
+                       reg_field_info[field].offset,
+                       reg_field_info[field].width);
+}
+
+static void gen_set_usr_fieldi(int field, int x)
+{
+    TCGv val = tcg_const_tl(x);
+    gen_set_usr_field(field, val);
+    tcg_temp_free(val);
+}
+
+static void gen_sat_i64(TCGv_i64 dst, TCGv_i64 src, uint32_t bits)
+{
+    TCGLabel *label = gen_new_label();
+
+    tcg_gen_sextract_i64(dst, src, 0, bits);
+    tcg_gen_brcond_i64(TCG_COND_EQ, dst, src, label);
+    {
+        TCGv_i64 min = tcg_constant_i64(-(1LL << (bits - 1)));
+        TCGv_i64 max = tcg_constant_i64((1LL << (bits - 1)) - 1);
+        tcg_gen_movcond_i64(TCG_COND_LT, dst, src, tcg_constant_i64(0),
+                            min, max);
+        gen_set_usr_fieldi(USR_OVF, 1);
+    }
+    gen_set_label(label);
+}
+
+static void gen_satval(TCGv_i64 dest, TCGv_i64 source, uint32_t bits)
+{
+    TCGv_i64 min = tcg_constant_i64(-(1LL << (bits - 1)));
+    TCGv_i64 max = tcg_constant_i64((1LL << (bits - 1)) - 1);
+
+    gen_set_usr_fieldi(USR_OVF, 1);
+    tcg_gen_movcond_i64(TCG_COND_LT, dest, source, tcg_constant_i64(0),
+                        min, max);
+}
+
+/* Shift left with saturation */
+static void gen_shl_sat(TCGv RdV, TCGv RsV, TCGv shift_amt)
+{
+    /*
+     * int64_t A = (fCAST4_8s(RsV) << shift_amt;
+     * if (((int32_t)((fSAT(A)) ^ ((int32_t)(RsV)))) < 0) {
+     *     RdV = fSATVALN(32, ((int32_t)(RsV)))
+     * } else if (((RsV) > 0) && ((A) == 0)) {
+     *     RdV = fSATVALN(32, (RsV));
+     * } else {
+     *     RdV = fSAT(A);
+     * }
+     */
+    TCGv_i64 RsV_i64 = tcg_temp_local_new_i64();
+    TCGv_i64 shift_amt_i64 = tcg_temp_local_new_i64();
+    TCGv_i64 A = tcg_temp_local_new_i64();
+    TCGv_i64 A_sat_i64 = tcg_temp_local_new_i64();
+    TCGv A_sat = tcg_temp_local_new();
+    TCGv_i64 RdV_i64 = tcg_temp_local_new_i64();
+    TCGv tmp = tcg_temp_new();
+    TCGLabel *label1 = gen_new_label();
+    TCGLabel *label2 = gen_new_label();
+    TCGLabel *done = gen_new_label();
+
+    tcg_gen_ext_i32_i64(RsV_i64, RsV);
+    tcg_gen_ext_i32_i64(shift_amt_i64, shift_amt);
+    tcg_gen_shl_i64(A, RsV_i64, shift_amt_i64);
+
+    /* Check for saturation */
+    gen_sat_i64(A_sat_i64, A, 32);
+    tcg_gen_extrl_i64_i32(A_sat, A_sat_i64);
+    tcg_gen_xor_tl(tmp, A_sat, RsV);
+    tcg_gen_brcondi_tl(TCG_COND_GE, tmp, 0, label1);
+    gen_satval(RdV_i64, RsV_i64, 32);
+    tcg_gen_extrl_i64_i32(RdV, RdV_i64);
+    tcg_gen_br(done);
+
+    gen_set_label(label1);
+    tcg_gen_brcondi_tl(TCG_COND_LE, RsV, 0, label2);
+    tcg_gen_brcondi_i64(TCG_COND_NE, A, 0, label2);
+    gen_satval(RdV_i64, RsV_i64, 32);
+    tcg_gen_extrl_i64_i32(RdV, RdV_i64);
+    tcg_gen_br(done);
+
+    gen_set_label(label2);
+    tcg_gen_mov_tl(RdV, A_sat);
+
+    gen_set_label(done);
+
+    tcg_temp_free_i64(RsV_i64);
+    tcg_temp_free_i64(shift_amt_i64);
+    tcg_temp_free_i64(A);
+    tcg_temp_free_i64(A_sat_i64);
+    tcg_temp_free(A_sat);
+    tcg_temp_free_i64(RdV_i64);
+    tcg_temp_free(tmp);
+}
+
+/* Bidirectional shift right with saturation */
+static void gen_asr_r_r_sat(TCGv RdV, TCGv RsV, TCGv RtV)
+{
+    TCGv shift_amt = tcg_temp_local_new();
+    TCGLabel *positive = gen_new_label();
+    TCGLabel *done = gen_new_label();
+
+    tcg_gen_sextract_i32(shift_amt, RtV, 0, 7);
+    tcg_gen_brcondi_tl(TCG_COND_GE, shift_amt, 0, positive);
+
+    /* Negative shift amount => shift left */
+    tcg_gen_neg_tl(shift_amt, shift_amt);
+    gen_shl_sat(RdV, RsV, shift_amt);
+    tcg_gen_br(done);
+
+    gen_set_label(positive);
+    /* Positive shift amount => shift right */
+    tcg_gen_sar_tl(RdV, RsV, shift_amt);
+
+    gen_set_label(done);
+
+    tcg_temp_free(shift_amt);
+}
+
+/* Bidirectional shift left with saturation */
+static void gen_asl_r_r_sat(TCGv RdV, TCGv RsV, TCGv RtV)
+{
+    TCGv shift_amt = tcg_temp_local_new();
+    TCGLabel *positive = gen_new_label();
+    TCGLabel *done = gen_new_label();
+
+    tcg_gen_sextract_i32(shift_amt, RtV, 0, 7);
+    tcg_gen_brcondi_tl(TCG_COND_GE, shift_amt, 0, positive);
+
+    /* Negative shift amount => shift right */
+    tcg_gen_neg_tl(shift_amt, shift_amt);
+    tcg_gen_sar_tl(RdV, RsV, shift_amt);
+    tcg_gen_br(done);
+
+    gen_set_label(positive);
+    /* Positive shift amount => shift left */
+    gen_shl_sat(RdV, RsV, shift_amt);
+
+    gen_set_label(done);
+
+    tcg_temp_free(shift_amt);
+}
+
 static intptr_t vreg_src_off(DisasContext *ctx, int num)
 {
     intptr_t offset = offsetof(CPUHexagonState, VRegs[num]);
diff --git a/tests/tcg/hexagon/usr.c b/tests/tcg/hexagon/usr.c
index a531511cec..e32c5e32a8 100644
--- a/tests/tcg/hexagon/usr.c
+++ b/tests/tcg/hexagon/usr.c
@@ -427,6 +427,7 @@ FUNC_P_OP_P(vabshsat,           "%0 = vabsh(%2):sat")
 FUNC_P_OP_PP(vnavgwr,           "%0 = vnavgw(%2, %3):rnd:sat")
 FUNC_R_OP_RI(round_ri_sat,      "%0 = round(%2, #%3):sat")
 FUNC_R_OP_RR(asr_r_r_sat,       "%0 = asr(%2, %3):sat")
+FUNC_R_OP_RR(asl_r_r_sat,       "%0 = asl(%2, %3):sat")
 
 FUNC_XPp_OP_PP(ACS,             "%0, p2 = vacsh(%3, %4)")
 
@@ -905,12 +906,21 @@ int main()
     TEST_R_OP_RI(round_ri_sat,         0x0000ffff, 2, 0x00004000, USR_CLEAR);
     TEST_R_OP_RI(round_ri_sat,         0x7fffffff, 2, 0x1fffffff, USR_OVF);
 
-    TEST_R_OP_RR(asr_r_r_sat,          0x0000ffff, 0x00000002, 0x00003fff,
-                 USR_CLEAR);
-    TEST_R_OP_RR(asr_r_r_sat,          0x00ffffff, 0xfffffff5, 0x7fffffff,
-                 USR_OVF);
-    TEST_R_OP_RR(asr_r_r_sat,          0x80000000, 0xfffffff5, 0x80000000,
-                 USR_OVF);
+    TEST_R_OP_RR(asr_r_r_sat,  0x0000ffff, 0x02, 0x00003fff, USR_CLEAR);
+    TEST_R_OP_RR(asr_r_r_sat,  0x80000000, 0x01, 0xc0000000, USR_CLEAR);
+    TEST_R_OP_RR(asr_r_r_sat,  0xffffffff, 0x01, 0xffffffff, USR_CLEAR);
+    TEST_R_OP_RR(asr_r_r_sat,  0x00ffffff, 0xf5, 0x7fffffff, USR_OVF);
+    TEST_R_OP_RR(asr_r_r_sat,  0x80000000, 0xf5, 0x80000000, USR_OVF);
+    TEST_R_OP_RR(asr_r_r_sat,  0x7fff0000, 0x42, 0x7fffffff, USR_OVF);
+    TEST_R_OP_RR(asr_r_r_sat,  0xff000000, 0x42, 0x80000000, USR_OVF);
+
+    TEST_R_OP_RR(asl_r_r_sat,  0x00000000, 0x40, 0x00000000, USR_CLEAR);
+    TEST_R_OP_RR(asl_r_r_sat,  0x80000000, 0xff, 0xc0000000, USR_CLEAR);
+    TEST_R_OP_RR(asl_r_r_sat,  0xffffffff, 0xff, 0xffffffff, USR_CLEAR);
+    TEST_R_OP_RR(asl_r_r_sat,  0x00ffffff, 0x0b, 0x7fffffff, USR_OVF);
+    TEST_R_OP_RR(asl_r_r_sat,  0x80000000, 0x0b, 0x80000000, USR_OVF);
+    TEST_R_OP_RR(asl_r_r_sat,  0x7fff0000, 0xbe, 0x7fffffff, USR_OVF);
+    TEST_R_OP_RR(asl_r_r_sat,  0xff000000, 0xbe, 0x80000000, USR_OVF);
 
     TEST_XPp_OP_PP(ACS, 0x0004000300020001ULL, 0x0001000200030004ULL,
                    0x0000000000000000ULL, 0x0004000300030004ULL, 0xf0,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread
* [PATCH] Hexagon (target/hexagon) add overrides for S2_asr_r_r_sat/S2_asl_r_r_sat
@ 2022-04-21  1:42 Taylor Simpson
  2022-04-21  1:42 ` [PATCH] Hexagon (target/hexagon) remove unused encodings Taylor Simpson
  0 siblings, 1 reply; 11+ messages in thread
From: Taylor Simpson @ 2022-04-21  1:42 UTC (permalink / raw)
  To: qemu-devel; +Cc: ale, bcain, richard.henderson, f4bug, tsimpson, mlambert

These instructions will not be generated by idef-parser, so we override
them manually.

Test cases added to tests/tcg/hexagon/usr.c

Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
---
 target/hexagon/gen_tcg.h |  10 ++-
 target/hexagon/genptr.c  | 147 +++++++++++++++++++++++++++++++++++++++
 tests/tcg/hexagon/usr.c  |  22 ++++--
 3 files changed, 172 insertions(+), 7 deletions(-)

diff --git a/target/hexagon/gen_tcg.h b/target/hexagon/gen_tcg.h
index c6f0879b6e..9268f49acd 100644
--- a/target/hexagon/gen_tcg.h
+++ b/target/hexagon/gen_tcg.h
@@ -1,5 +1,5 @@
 /*
- *  Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *  Copyright(c) 2019-2022 Qualcomm Innovation Center, Inc. All Rights Reserved.
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -610,6 +610,14 @@
         tcg_temp_free(tmp); \
     } while (0)
 
+/* r0 = asr(r1, r2):sat */
+#define fGEN_TCG_S2_asr_r_r_sat(SHORTCODE) \
+    gen_asr_r_r_sat(RdV, RsV, RtV)
+
+/* r0 = asl(r1, r2):sat */
+#define fGEN_TCG_S2_asl_r_r_sat(SHORTCODE) \
+    gen_asl_r_r_sat(RdV, RsV, RtV)
+
 /* Floating point */
 #define fGEN_TCG_F2_conv_sf2df(SHORTCODE) \
     gen_helper_conv_sf2df(RddV, cpu_env, RsV)
diff --git a/target/hexagon/genptr.c b/target/hexagon/genptr.c
index cd6af4bceb..36e6451859 100644
--- a/target/hexagon/genptr.c
+++ b/target/hexagon/genptr.c
@@ -468,6 +468,153 @@ static TCGv gen_8bitsof(TCGv result, TCGv value)
     return result;
 }
 
+static void gen_set_usr_field(int field, TCGv val)
+{
+    tcg_gen_deposit_tl(hex_new_value[HEX_REG_USR], hex_new_value[HEX_REG_USR],
+                       val,
+                       reg_field_info[field].offset,
+                       reg_field_info[field].width);
+}
+
+static void gen_set_usr_fieldi(int field, int x)
+{
+    TCGv val = tcg_const_tl(x);
+    gen_set_usr_field(field, val);
+    tcg_temp_free(val);
+}
+
+static void gen_sat_i64(TCGv_i64 dst, TCGv_i64 src, uint32_t bits)
+{
+    TCGLabel *label = gen_new_label();
+
+    tcg_gen_sextract_i64(dst, src, 0, bits);
+    tcg_gen_brcond_i64(TCG_COND_EQ, dst, src, label);
+    {
+        TCGv_i64 min = tcg_constant_i64(-(1LL << (bits - 1)));
+        TCGv_i64 max = tcg_constant_i64((1LL << (bits - 1)) - 1);
+        tcg_gen_movcond_i64(TCG_COND_LT, dst, src, tcg_constant_i64(0),
+                            min, max);
+        gen_set_usr_fieldi(USR_OVF, 1);
+    }
+    gen_set_label(label);
+}
+
+static void gen_satval(TCGv_i64 dest, TCGv_i64 source, uint32_t bits)
+{
+    TCGv_i64 min = tcg_constant_i64(-(1LL << (bits - 1)));
+    TCGv_i64 max = tcg_constant_i64((1LL << (bits - 1)) - 1);
+
+    gen_set_usr_fieldi(USR_OVF, 1);
+    tcg_gen_movcond_i64(TCG_COND_LT, dest, source, tcg_constant_i64(0),
+                        min, max);
+}
+
+/* Shift left with saturation */
+static void gen_shl_sat(TCGv RdV, TCGv RsV, TCGv shift_amt)
+{
+    /*
+     * int64_t A = (fCAST4_8s(RsV) << shift_amt;
+     * if (((int32_t)((fSAT(A)) ^ ((int32_t)(RsV)))) < 0) {
+     *     RdV = fSATVALN(32, ((int32_t)(RsV)))
+     * } else if (((RsV) > 0) && ((A) == 0)) {
+     *     RdV = fSATVALN(32, (RsV));
+     * } else {
+     *     RdV = fSAT(A);
+     * }
+     */
+    TCGv_i64 RsV_i64 = tcg_temp_local_new_i64();
+    TCGv_i64 shift_amt_i64 = tcg_temp_local_new_i64();
+    TCGv_i64 A = tcg_temp_local_new_i64();
+    TCGv_i64 A_sat_i64 = tcg_temp_local_new_i64();
+    TCGv A_sat = tcg_temp_local_new();
+    TCGv_i64 RdV_i64 = tcg_temp_local_new_i64();
+    TCGv tmp = tcg_temp_new();
+    TCGLabel *label1 = gen_new_label();
+    TCGLabel *label2 = gen_new_label();
+    TCGLabel *done = gen_new_label();
+
+    tcg_gen_ext_i32_i64(RsV_i64, RsV);
+    tcg_gen_ext_i32_i64(shift_amt_i64, shift_amt);
+    tcg_gen_shl_i64(A, RsV_i64, shift_amt_i64);
+
+    /* Check for saturation */
+    gen_sat_i64(A_sat_i64, A, 32);
+    tcg_gen_extrl_i64_i32(A_sat, A_sat_i64);
+    tcg_gen_xor_tl(tmp, A_sat, RsV);
+    tcg_gen_brcondi_tl(TCG_COND_GE, tmp, 0, label1);
+    gen_satval(RdV_i64, RsV_i64, 32);
+    tcg_gen_extrl_i64_i32(RdV, RdV_i64);
+    tcg_gen_br(done);
+
+    gen_set_label(label1);
+    tcg_gen_brcondi_tl(TCG_COND_LE, RsV, 0, label2);
+    tcg_gen_brcondi_i64(TCG_COND_NE, A, 0, label2);
+    gen_satval(RdV_i64, RsV_i64, 32);
+    tcg_gen_extrl_i64_i32(RdV, RdV_i64);
+    tcg_gen_br(done);
+
+    gen_set_label(label2);
+    tcg_gen_mov_tl(RdV, A_sat);
+
+    gen_set_label(done);
+
+    tcg_temp_free_i64(RsV_i64);
+    tcg_temp_free_i64(shift_amt_i64);
+    tcg_temp_free_i64(A);
+    tcg_temp_free_i64(A_sat_i64);
+    tcg_temp_free(A_sat);
+    tcg_temp_free_i64(RdV_i64);
+    tcg_temp_free(tmp);
+}
+
+/* Bidirectional shift right with saturation */
+static void gen_asr_r_r_sat(TCGv RdV, TCGv RsV, TCGv RtV)
+{
+    TCGv shift_amt = tcg_temp_local_new();
+    TCGLabel *positive = gen_new_label();
+    TCGLabel *done = gen_new_label();
+
+    tcg_gen_sextract_i32(shift_amt, RtV, 0, 7);
+    tcg_gen_brcondi_tl(TCG_COND_GE, shift_amt, 0, positive);
+
+    /* Negative shift amount => shift left */
+    tcg_gen_neg_tl(shift_amt, shift_amt);
+    gen_shl_sat(RdV, RsV, shift_amt);
+    tcg_gen_br(done);
+
+    gen_set_label(positive);
+    /* Positive shift amount => shift right */
+    tcg_gen_sar_tl(RdV, RsV, shift_amt);
+
+    gen_set_label(done);
+
+    tcg_temp_free(shift_amt);
+}
+
+/* Bidirectional shift left with saturation */
+static void gen_asl_r_r_sat(TCGv RdV, TCGv RsV, TCGv RtV)
+{
+    TCGv shift_amt = tcg_temp_local_new();
+    TCGLabel *positive = gen_new_label();
+    TCGLabel *done = gen_new_label();
+
+    tcg_gen_sextract_i32(shift_amt, RtV, 0, 7);
+    tcg_gen_brcondi_tl(TCG_COND_GE, shift_amt, 0, positive);
+
+    /* Negative shift amount => shift right */
+    tcg_gen_neg_tl(shift_amt, shift_amt);
+    tcg_gen_sar_tl(RdV, RsV, shift_amt);
+    tcg_gen_br(done);
+
+    gen_set_label(positive);
+    /* Positive shift amount => shift left */
+    gen_shl_sat(RdV, RsV, shift_amt);
+
+    gen_set_label(done);
+
+    tcg_temp_free(shift_amt);
+}
+
 static intptr_t vreg_src_off(DisasContext *ctx, int num)
 {
     intptr_t offset = offsetof(CPUHexagonState, VRegs[num]);
diff --git a/tests/tcg/hexagon/usr.c b/tests/tcg/hexagon/usr.c
index a531511cec..e32c5e32a8 100644
--- a/tests/tcg/hexagon/usr.c
+++ b/tests/tcg/hexagon/usr.c
@@ -427,6 +427,7 @@ FUNC_P_OP_P(vabshsat,           "%0 = vabsh(%2):sat")
 FUNC_P_OP_PP(vnavgwr,           "%0 = vnavgw(%2, %3):rnd:sat")
 FUNC_R_OP_RI(round_ri_sat,      "%0 = round(%2, #%3):sat")
 FUNC_R_OP_RR(asr_r_r_sat,       "%0 = asr(%2, %3):sat")
+FUNC_R_OP_RR(asl_r_r_sat,       "%0 = asl(%2, %3):sat")
 
 FUNC_XPp_OP_PP(ACS,             "%0, p2 = vacsh(%3, %4)")
 
@@ -905,12 +906,21 @@ int main()
     TEST_R_OP_RI(round_ri_sat,         0x0000ffff, 2, 0x00004000, USR_CLEAR);
     TEST_R_OP_RI(round_ri_sat,         0x7fffffff, 2, 0x1fffffff, USR_OVF);
 
-    TEST_R_OP_RR(asr_r_r_sat,          0x0000ffff, 0x00000002, 0x00003fff,
-                 USR_CLEAR);
-    TEST_R_OP_RR(asr_r_r_sat,          0x00ffffff, 0xfffffff5, 0x7fffffff,
-                 USR_OVF);
-    TEST_R_OP_RR(asr_r_r_sat,          0x80000000, 0xfffffff5, 0x80000000,
-                 USR_OVF);
+    TEST_R_OP_RR(asr_r_r_sat,  0x0000ffff, 0x02, 0x00003fff, USR_CLEAR);
+    TEST_R_OP_RR(asr_r_r_sat,  0x80000000, 0x01, 0xc0000000, USR_CLEAR);
+    TEST_R_OP_RR(asr_r_r_sat,  0xffffffff, 0x01, 0xffffffff, USR_CLEAR);
+    TEST_R_OP_RR(asr_r_r_sat,  0x00ffffff, 0xf5, 0x7fffffff, USR_OVF);
+    TEST_R_OP_RR(asr_r_r_sat,  0x80000000, 0xf5, 0x80000000, USR_OVF);
+    TEST_R_OP_RR(asr_r_r_sat,  0x7fff0000, 0x42, 0x7fffffff, USR_OVF);
+    TEST_R_OP_RR(asr_r_r_sat,  0xff000000, 0x42, 0x80000000, USR_OVF);
+
+    TEST_R_OP_RR(asl_r_r_sat,  0x00000000, 0x40, 0x00000000, USR_CLEAR);
+    TEST_R_OP_RR(asl_r_r_sat,  0x80000000, 0xff, 0xc0000000, USR_CLEAR);
+    TEST_R_OP_RR(asl_r_r_sat,  0xffffffff, 0xff, 0xffffffff, USR_CLEAR);
+    TEST_R_OP_RR(asl_r_r_sat,  0x00ffffff, 0x0b, 0x7fffffff, USR_OVF);
+    TEST_R_OP_RR(asl_r_r_sat,  0x80000000, 0x0b, 0x80000000, USR_OVF);
+    TEST_R_OP_RR(asl_r_r_sat,  0x7fff0000, 0xbe, 0x7fffffff, USR_OVF);
+    TEST_R_OP_RR(asl_r_r_sat,  0xff000000, 0xbe, 0x80000000, USR_OVF);
 
     TEST_XPp_OP_PP(ACS, 0x0004000300020001ULL, 0x0001000200030004ULL,
                    0x0000000000000000ULL, 0x0004000300030004ULL, 0xf0,
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2022-06-07 10:22 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-09 21:14 [PATCH] Hexagon (target/hexagon) add overrides for S2_asr_r_r_sat/S2_asl_r_r_sat Taylor Simpson
2022-05-09 21:14 ` [PATCH] Hexagon (target/hexagon) make VyV operands use a unique temp Taylor Simpson
2022-05-09 21:14 ` [PATCH] Hexagon (target/hexagon) move store size tracking to translation Taylor Simpson
2022-05-09 21:31   ` Philippe Mathieu-Daudé via
2022-05-09 21:14 ` [PATCH] Hexagon (target/hexagon) remove unused encodings Taylor Simpson
2022-05-09 21:31   ` Philippe Mathieu-Daudé via
2022-05-09 21:14 ` [PATCH] Hexagon (tests/tcg/hexagon) Fix alignment in load_unpack.c Taylor Simpson
2022-05-09 21:14 ` [PATCH] Hexagon (tests/tcg/hexagon) reference file for float_convd Taylor Simpson
  -- strict thread matches above, loose matches on Subject: below --
2022-06-06 22:23 [PATCH] Hexagon (target/hexagon) add overrides for S2_asr_r_r_sat/S2_asl_r_r_sat Taylor Simpson
2022-06-06 22:23 ` [PATCH] Hexagon (target/hexagon) remove unused encodings Taylor Simpson
2022-06-07 10:08   ` Philippe Mathieu-Daudé via
2022-04-21  1:42 [PATCH] Hexagon (target/hexagon) add overrides for S2_asr_r_r_sat/S2_asl_r_r_sat Taylor Simpson
2022-04-21  1:42 ` [PATCH] Hexagon (target/hexagon) remove unused encodings Taylor Simpson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.