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 99029be1c2
("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>
This commit is contained in:
parent
9a4e273dde
commit
9253773cb7
8 changed files with 78 additions and 4 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ mips_ss.add(files(
|
|||
'gdbstub.c',
|
||||
'msa.c',
|
||||
))
|
||||
mips_ss.add(zlib)
|
||||
|
||||
if have_system
|
||||
subdir('system')
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue