diff mbox series

[02/10] target/tricore: Implement CRCN insn

Message ID 20230826160242.312052-3-kbastian@mail.uni-paderborn.de (mailing list archive)
State New, archived
Headers show
Series TriCore 1.6.2 insn and bugfixes | expand

Commit Message

Bastian Koppelmann Aug. 26, 2023, 4:02 p.m. UTC
reported in https://gitlab.com/qemu-project/qemu/-/issues/1667

Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
---
 target/tricore/helper.h                   |  1 +
 target/tricore/op_helper.c                | 66 +++++++++++++++++++++++
 target/tricore/translate.c                |  6 +++
 target/tricore/tricore-opcodes.h          |  1 +
 tests/tcg/tricore/Makefile.softmmu-target |  1 +
 tests/tcg/tricore/asm/test_crcn.S         |  9 ++++
 6 files changed, 84 insertions(+)
 create mode 100644 tests/tcg/tricore/asm/test_crcn.S

Comments

Richard Henderson Aug. 27, 2023, 4:33 a.m. UTC | #1
On 8/26/23 09:02, Bastian Koppelmann wrote:
> +static uint32_t crc_div(uint32_t crc_in, uint32_t data, uint32_t gen,
> +                        uint32_t n, uint32_t m)
> +{
> +    uint32_t i;
> +
> +    data = data << n;
> +    data = deposit32(data, m, 32 - m, 0);

This is data = extract32(data, 0, m), however...

> +    for (i = 0; i < m; i++) {
> +
> +        if (crc_in & (1u << (n - 1))) {
> +            crc_in <<= 1;
> +            if (data & (1u << (m - 1))) {

You only check a single bit of data here, always bit m-1.

> +                crc_in++;
> +            }
> +            crc_in ^= gen;
> +        } else {
> +            crc_in <<= 1;
> +            if (data & (1u << (m - 1))) {
> +                crc_in++;
> +            }
> +        }
> +        data <<= 1;
> +        data = deposit32(data, m, 32 - m, 0);

So why do you need to keep bits above m clear?
I think you should just shift left and let bits fall off the left naturally.

> +    return deposit32(crc_out, n, 32 - n, 0);

extract32(crc_out, 0, n);

> +}
> +
>   uint32_t helper_shuffle(uint32_t arg0, uint32_t arg1)
>   {
>       uint32_t resb;
> diff --git a/target/tricore/translate.c b/target/tricore/translate.c
> index 1947733870..bb7dad75d6 100644
> --- a/target/tricore/translate.c
> +++ b/target/tricore/translate.c
> @@ -6673,6 +6673,12 @@ static void decode_rrr_divide(DisasContext *ctx)
>           gen_helper_pack(cpu_gpr_d[r4], cpu_PSW_C, cpu_gpr_d[r3],
>                           cpu_gpr_d[r3+1], cpu_gpr_d[r1]);
>           break;
> +    case OPC2_32_RRR_CRCN:
> +        if (has_feature(ctx, TRICORE_FEATURE_162)) {
> +            gen_helper_crcn(cpu_gpr_d[r4], cpu_gpr_d[r1], cpu_gpr_d[r2],
> +                            cpu_gpr_d[r3]);
> +        }
> +        break;

trap if not feature 162.


r~
diff mbox series

Patch

diff --git a/target/tricore/helper.h b/target/tricore/helper.h
index 31d71eac7a..190645413a 100644
--- a/target/tricore/helper.h
+++ b/target/tricore/helper.h
@@ -134,6 +134,7 @@  DEF_HELPER_FLAGS_5(mulr_h, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32, i32, i32)
 DEF_HELPER_FLAGS_2(crc32b, TCG_CALL_NO_RWG_SE, i32, i32, i32)
 DEF_HELPER_FLAGS_2(crc32_be, TCG_CALL_NO_RWG_SE, i32, i32, i32)
 DEF_HELPER_FLAGS_2(crc32_le, TCG_CALL_NO_RWG_SE, i32, i32, i32)
+DEF_HELPER_FLAGS_3(crcn, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
 DEF_HELPER_FLAGS_2(shuffle, TCG_CALL_NO_RWG_SE, i32, i32, i32)
 /* CSA */
 DEF_HELPER_2(call, void, env, i32)
diff --git a/target/tricore/op_helper.c b/target/tricore/op_helper.c
index 89be1ed648..6445fd334b 100644
--- a/target/tricore/op_helper.c
+++ b/target/tricore/op_helper.c
@@ -2308,6 +2308,72 @@  uint32_t helper_crc32_le(uint32_t arg0, uint32_t arg1)
     return crc32(arg1, buf, 4);
 }
 
+static uint32_t crc_div(uint32_t crc_in, uint32_t data, uint32_t gen,
+                        uint32_t n, uint32_t m)
+{
+    uint32_t i;
+
+    data = data << n;
+    data = deposit32(data, m, 32 - m, 0);
+    for (i = 0; i < m; i++) {
+
+        if (crc_in & (1u << (n - 1))) {
+            crc_in <<= 1;
+            if (data & (1u << (m - 1))) {
+                crc_in++;
+            }
+            crc_in ^= gen;
+        } else {
+            crc_in <<= 1;
+            if (data & (1u << (m - 1))) {
+                crc_in++;
+            }
+        }
+        data <<= 1;
+        data = deposit32(data, m, 32 - m, 0);
+    }
+
+    return crc_in;
+}
+
+uint32_t helper_crcn(uint32_t arg0, uint32_t arg1, uint32_t arg2)
+{
+    uint32_t crc_out, crc_in;
+    uint32_t n = extract32(arg0, 12, 4) + 1;
+    uint32_t gen = extract32(arg0, 16, n);
+    uint32_t inv = extract32(arg0, 9, 1);
+    uint32_t le = extract32(arg0, 8, 1);
+    uint32_t m = extract32(arg0, 0, 3) + 1;
+    uint32_t data = extract32(arg1, 0, m);
+    uint32_t seed = extract32(arg2, 0, n);
+
+    if (le == 1) {
+        if (m == 0) {
+            data = 0;
+        } else {
+            data = revbit32(data) >> (32 - m);
+        }
+    }
+
+    if (inv == 1) {
+        seed = ~seed;
+    }
+
+    if (m > n) {
+        crc_in = (data >> (m - n)) ^ seed;
+    } else {
+        crc_in = (data << (n - m)) ^ seed;
+    }
+
+    crc_out = crc_div(crc_in, data, gen, n, m);
+
+    if (inv) {
+        crc_out = ~crc_out;
+    }
+
+    return deposit32(crc_out, n, 32 - n, 0);
+}
+
 uint32_t helper_shuffle(uint32_t arg0, uint32_t arg1)
 {
     uint32_t resb;
diff --git a/target/tricore/translate.c b/target/tricore/translate.c
index 1947733870..bb7dad75d6 100644
--- a/target/tricore/translate.c
+++ b/target/tricore/translate.c
@@ -6673,6 +6673,12 @@  static void decode_rrr_divide(DisasContext *ctx)
         gen_helper_pack(cpu_gpr_d[r4], cpu_PSW_C, cpu_gpr_d[r3],
                         cpu_gpr_d[r3+1], cpu_gpr_d[r1]);
         break;
+    case OPC2_32_RRR_CRCN:
+        if (has_feature(ctx, TRICORE_FEATURE_162)) {
+            gen_helper_crcn(cpu_gpr_d[r4], cpu_gpr_d[r1], cpu_gpr_d[r2],
+                            cpu_gpr_d[r3]);
+        }
+        break;
     case OPC2_32_RRR_ADD_F:
         gen_helper_fadd(cpu_gpr_d[r4], cpu_env, cpu_gpr_d[r1], cpu_gpr_d[r3]);
         break;
diff --git a/target/tricore/tricore-opcodes.h b/target/tricore/tricore-opcodes.h
index bc62b73173..f070571665 100644
--- a/target/tricore/tricore-opcodes.h
+++ b/target/tricore/tricore-opcodes.h
@@ -1247,6 +1247,7 @@  enum {
     OPC2_32_RRR_SUB_F                            = 0x03,
     OPC2_32_RRR_MADD_F                           = 0x06,
     OPC2_32_RRR_MSUB_F                           = 0x07,
+    OPC2_32_RRR_CRCN                             = 0x01, /* 1.6.2 up */
 };
 /*
  * RRR1 Format
diff --git a/tests/tcg/tricore/Makefile.softmmu-target b/tests/tcg/tricore/Makefile.softmmu-target
index f8fd207921..7a7d73a60c 100644
--- a/tests/tcg/tricore/Makefile.softmmu-target
+++ b/tests/tcg/tricore/Makefile.softmmu-target
@@ -9,6 +9,7 @@  CFLAGS = -mtc162 -c -I$(TESTS_PATH)
 TESTS += test_abs.asm.tst
 TESTS += test_bmerge.asm.tst
 TESTS += test_clz.asm.tst
+TESTS += test_crcn.asm.tst
 TESTS += test_dextr.asm.tst
 TESTS += test_dvstep.asm.tst
 TESTS += test_fadd.asm.tst
diff --git a/tests/tcg/tricore/asm/test_crcn.S b/tests/tcg/tricore/asm/test_crcn.S
new file mode 100644
index 0000000000..51a22722a3
--- /dev/null
+++ b/tests/tcg/tricore/asm/test_crcn.S
@@ -0,0 +1,9 @@ 
+#include "macros.h"
+.text
+.global _start
+_start:
+#                insn num    result   rs1    rs2     rs3
+#                 |     |      |      |       |       |
+    TEST_D_DDD(crcn, 1, 0x00002bed, 0x0, 0xa10ddeed, 0x0)
+
+    TEST_PASSFAIL