aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYongbok Kim <yongbok.kim@mips.com>2019-07-29 19:23:33 +0200
committerPhilippe Mathieu-Daudé <philmd@linaro.org>2025-07-15 00:07:46 +0200
commit9253773cb7ff10d85ccaf4d5f418ea5c7fa31834 (patch)
tree414f8639d75c0788a5eedc7e485ceca123cb6f1c
parent9a4e273ddec3927920c5958d2226c6b38b543336 (diff)
downloadqemu-9253773cb7ff10d85ccaf4d5f418ea5c7fa31834.zip
qemu-9253773cb7ff10d85ccaf4d5f418ea5c7fa31834.tar.gz
qemu-9253773cb7ff10d85ccaf4d5f418ea5c7fa31834.tar.bz2
target/mips: Add support for emulation of CRC32 instructions
Add emulation of MIPS' CRC32 (Cyclic Redundancy Check) instructions. Reuse zlib crc32() and Linux crc32c(). Corresponding disassembly has been added in commit 99029be1c28 ("target/mips: Add implementation of GINVT instruction"). Signed-off-by: Yongbok Kim <yongbok.kim@mips.com> Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com> Signed-off-by: Aleksandar Rakic <aleksandar.rakic@htecgroup.com> Reviewed-by: Aleksandar Rikalo <arikalo@gmail.com> Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-ID: <PA4PR09MB486489692D843DDFC25F3CF1846B2@PA4PR09MB4864.eurprd09.prod.outlook.com>
-rw-r--r--target/mips/cpu-defs.c.inc10
-rw-r--r--target/mips/helper.h2
-rw-r--r--target/mips/meson.build1
-rw-r--r--target/mips/tcg/op_helper.c26
-rw-r--r--target/mips/tcg/rel6.decode5
-rw-r--r--target/mips/tcg/rel6_translate.c12
-rw-r--r--target/mips/tcg/translate.c24
-rw-r--r--target/mips/tcg/translate.h2
8 files changed, 78 insertions, 4 deletions
diff --git a/target/mips/cpu-defs.c.inc b/target/mips/cpu-defs.c.inc
index 922fc39..d93b9d3 100644
--- a/target/mips/cpu-defs.c.inc
+++ b/target/mips/cpu-defs.c.inc
@@ -756,8 +756,9 @@ const mips_def_t mips_defs[] =
(1 << CP0C3_RXI) | (1 << CP0C3_LPA) | (1 << CP0C3_VInt),
.CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (3 << CP0C4_IE) |
(1 << CP0C4_AE) | (0xfc << CP0C4_KScrExist),
- .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_XNP) | (1 << CP0C5_VP) |
- (1 << CP0C5_LLB) | (1 << CP0C5_MRP) | (3 << CP0C5_GI),
+ .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_CRCP) | (1 << CP0C5_XNP) |
+ (1 << CP0C5_VP) | (1 << CP0C5_LLB) | (1 << CP0C5_MRP) |
+ (3 << CP0C5_GI),
.CP0_Config5_rw_bitmask = (1 << CP0C5_MSAEn) | (1 << CP0C5_SBRI) |
(1 << CP0C5_FRE) | (1 << CP0C5_UFE),
.CP0_LLAddr_rw_bitmask = 0,
@@ -796,8 +797,9 @@ const mips_def_t mips_defs[] =
(1 << CP0C3_RXI) | (1 << CP0C3_LPA) | (1 << CP0C3_VInt),
.CP0_Config4 = MIPS_CONFIG4 | (1U << CP0C4_M) | (3 << CP0C4_IE) |
(1 << CP0C4_AE) | (0xfc << CP0C4_KScrExist),
- .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_XNP) | (1 << CP0C5_VP) |
- (1 << CP0C5_LLB) | (1 << CP0C5_MRP) | (3 << CP0C5_GI),
+ .CP0_Config5 = MIPS_CONFIG5 | (1 << CP0C5_CRCP) | (1 << CP0C5_XNP) |
+ (1 << CP0C5_VP) | (1 << CP0C5_LLB) | (1 << CP0C5_MRP) |
+ (3 << CP0C5_GI),
.CP0_Config5_rw_bitmask = (1 << CP0C5_MSAEn) | (1 << CP0C5_SBRI) |
(1 << CP0C5_FRE) | (1 << CP0C5_UFE),
.CP0_LLAddr_rw_bitmask = 0,
diff --git a/target/mips/helper.h b/target/mips/helper.h
index 7e40041..b6cd53c 100644
--- a/target/mips/helper.h
+++ b/target/mips/helper.h
@@ -21,6 +21,8 @@ DEF_HELPER_FLAGS_1(bitswap, TCG_CALL_NO_RWG_SE, tl, tl)
DEF_HELPER_FLAGS_1(dbitswap, TCG_CALL_NO_RWG_SE, tl, tl)
#endif
+DEF_HELPER_3(crc32, tl, tl, tl, i32)
+DEF_HELPER_3(crc32c, tl, tl, tl, i32)
DEF_HELPER_FLAGS_4(rotx, TCG_CALL_NO_RWG_SE, tl, tl, i32, i32, i32)
/* microMIPS functions */
diff --git a/target/mips/meson.build b/target/mips/meson.build
index 247979a..abf0ce3 100644
--- a/target/mips/meson.build
+++ b/target/mips/meson.build
@@ -7,6 +7,7 @@ mips_ss.add(files(
'gdbstub.c',
'msa.c',
))
+mips_ss.add(zlib)
if have_system
subdir('system')
diff --git a/target/mips/tcg/op_helper.c b/target/mips/tcg/op_helper.c
index b906d10..4502ae2 100644
--- a/target/mips/tcg/op_helper.c
+++ b/target/mips/tcg/op_helper.c
@@ -24,6 +24,8 @@
#include "exec/helper-proto.h"
#include "exec/memop.h"
#include "fpu_helper.h"
+#include "qemu/crc32c.h"
+#include <zlib.h>
static inline target_ulong bitswap(target_ulong v)
{
@@ -142,6 +144,30 @@ target_ulong helper_rotx(target_ulong rs, uint32_t shift, uint32_t shiftx,
return (int64_t)(int32_t)(uint32_t)tmp5;
}
+/* these crc32 functions are based on target/loongarch/tcg/op_helper.c */
+target_ulong helper_crc32(target_ulong val, target_ulong m, uint32_t sz)
+{
+ uint8_t buf[8];
+ target_ulong mask = ((sz * 8) == 64) ?
+ (target_ulong) -1ULL :
+ ((1ULL << (sz * 8)) - 1);
+
+ m &= mask;
+ stq_le_p(buf, m);
+ return (int32_t) (crc32(val ^ 0xffffffff, buf, sz) ^ 0xffffffff);
+}
+
+target_ulong helper_crc32c(target_ulong val, target_ulong m, uint32_t sz)
+{
+ uint8_t buf[8];
+ target_ulong mask = ((sz * 8) == 64) ?
+ (target_ulong) -1ULL :
+ ((1ULL << (sz * 8)) - 1);
+ m &= mask;
+ stq_le_p(buf, m);
+ return (int32_t) (crc32c(val, buf, sz) ^ 0xffffffff);
+}
+
void helper_fork(target_ulong arg1, target_ulong arg2)
{
/*
diff --git a/target/mips/tcg/rel6.decode b/target/mips/tcg/rel6.decode
index d6989cf..7fbcb10 100644
--- a/target/mips/tcg/rel6.decode
+++ b/target/mips/tcg/rel6.decode
@@ -16,11 +16,16 @@
&r rs rt rd sa
+&special3_crc rs rt c sz
+
@lsa ...... rs:5 rt:5 rd:5 ... sa:2 ...... &r
+@crc32 ...... rs:5 rt:5 ..... c:3 sz:2 ...... &special3_crc
LSA 000000 ..... ..... ..... 000 .. 000101 @lsa
DLSA 000000 ..... ..... ..... 000 .. 010101 @lsa
+CRC32 011111 ..... ..... 00000 ... .. 001111 @crc32
+
REMOVED 010011 ----- ----- ----- ----- ------ # COP1X (COP3)
REMOVED 011100 ----- ----- ----- ----- ------ # SPECIAL2
diff --git a/target/mips/tcg/rel6_translate.c b/target/mips/tcg/rel6_translate.c
index 59f237b..8933506 100644
--- a/target/mips/tcg/rel6_translate.c
+++ b/target/mips/tcg/rel6_translate.c
@@ -33,3 +33,15 @@ static bool trans_DLSA(DisasContext *ctx, arg_r *a)
}
return gen_dlsa(ctx, a->rd, a->rt, a->rs, a->sa);
}
+
+static bool trans_CRC32(DisasContext *ctx, arg_special3_crc *a)
+{
+ if (unlikely(!ctx->crcp)
+ || unlikely((a->sz == 3) && (!(ctx->hflags & MIPS_HFLAG_64)))
+ || unlikely((a->c >= 2))) {
+ gen_reserved_instruction(ctx);
+ return true;
+ }
+ gen_crc32(ctx, a->rt, a->rs, a->rt, a->sz, a->c);
+ return true;
+}
diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c
index 8658315..5c80b03 100644
--- a/target/mips/tcg/translate.c
+++ b/target/mips/tcg/translate.c
@@ -13449,6 +13449,29 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
}
}
+void gen_crc32(DisasContext *ctx, int rd, int rs, int rt, int sz,
+ int crc32c)
+{
+ TCGv t0;
+ TCGv t1;
+ TCGv_i32 tsz = tcg_constant_i32(1 << sz);
+ if (rd == 0) {
+ /* Treat as NOP. */
+ return;
+ }
+ t0 = tcg_temp_new();
+ t1 = tcg_temp_new();
+
+ gen_load_gpr(t0, rt);
+ gen_load_gpr(t1, rs);
+
+ if (crc32c) {
+ gen_helper_crc32c(cpu_gpr[rd], t0, t1, tsz);
+ } else {
+ gen_helper_crc32(cpu_gpr[rd], t0, t1, tsz);
+ }
+}
+
static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
{
int rs, rt, rd, sa;
@@ -15095,6 +15118,7 @@ static void mips_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
ctx->abs2008 = (env->active_fpu.fcr31 >> FCR31_ABS2008) & 1;
ctx->mi = (env->CP0_Config5 >> CP0C5_MI) & 1;
ctx->gi = (env->CP0_Config5 >> CP0C5_GI) & 3;
+ ctx->crcp = (env->CP0_Config5 >> CP0C5_CRCP) & 1;
restore_cpu_state(env, ctx);
#ifdef CONFIG_USER_ONLY
ctx->mem_idx = MIPS_HFLAG_UM;
diff --git a/target/mips/tcg/translate.h b/target/mips/tcg/translate.h
index 1bf153d..428b53a 100644
--- a/target/mips/tcg/translate.h
+++ b/target/mips/tcg/translate.h
@@ -51,6 +51,7 @@ typedef struct DisasContext {
bool abs2008;
bool mi;
int gi;
+ bool crcp;
} DisasContext;
#define DISAS_STOP DISAS_TARGET_0
@@ -181,6 +182,7 @@ bool gen_lsa(DisasContext *ctx, int rd, int rt, int rs, int sa);
bool gen_dlsa(DisasContext *ctx, int rd, int rt, int rs, int sa);
void gen_rdhwr(DisasContext *ctx, int rt, int rd, int sel);
+void gen_crc32(DisasContext *ctx, int rd, int rs, int rt, int sz, int crc32c);
extern TCGv cpu_gpr[32], cpu_PC;
#if defined(TARGET_MIPS64)