From: Yongbok Kim <yongbok....@mips.com> 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....@mips.com> Signed-off-by: Aleksandar Markovic <amarko...@wavecomp.com> Signed-off-by: Aleksandar Rakic <aleksandar.ra...@htecgroup.com> Reviewed-by: Aleksandar Rikalo <arik...@gmail.com> Signed-off-by: Philippe Mathieu-Daudé <phi...@linaro.org> Message-ID: <pa4pr09mb486489692d843ddfc25f3cf184...@pa4pr09mb4864.eurprd09.prod.outlook.com> --- target/mips/helper.h | 2 ++ target/mips/tcg/translate.h | 2 ++ target/mips/tcg/rel6.decode | 5 +++++ target/mips/tcg/op_helper.c | 26 ++++++++++++++++++++++++++ target/mips/tcg/rel6_translate.c | 12 ++++++++++++ target/mips/tcg/translate.c | 24 ++++++++++++++++++++++++ target/mips/cpu-defs.c.inc | 10 ++++++---- target/mips/meson.build | 1 + 8 files changed, 78 insertions(+), 4 deletions(-) diff --git a/target/mips/helper.h b/target/mips/helper.h index 7e400418281..b6cd53c8538 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/tcg/translate.h b/target/mips/tcg/translate.h index 1bf153d1838..428b53a0dac 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) diff --git a/target/mips/tcg/rel6.decode b/target/mips/tcg/rel6.decode index d6989cf56e8..7fbcb109b4e 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/op_helper.c b/target/mips/tcg/op_helper.c index b906d10204b..4502ae2b5be 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_translate.c b/target/mips/tcg/rel6_translate.c index 59f237ba3ba..89335063977 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 8658315f938..5c80b030329 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/cpu-defs.c.inc b/target/mips/cpu-defs.c.inc index 922fc39138d..d93b9d341ac 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/meson.build b/target/mips/meson.build index 247979a2cfc..abf0ce3e8b9 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') -- 2.49.0