mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-02-02 17:51:06 +00:00
target-mips: refactor {D}LSA, {D}ALIGN, {D}BITSWAP
Refactor those instructions in order to reuse them for microMIPS32 Release 6. Rearrange gen_move_low32(). Backports commit 1f1b4c008e250f870719ed38fbd0bcc14322fc01 from qemu
This commit is contained in:
parent
14abf22311
commit
6e32aa7c3c
|
@ -1725,6 +1725,15 @@ static target_long addr_add(DisasContext *ctx, target_long base,
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void gen_move_low32(TCGContext *s, TCGv ret, TCGv_i64 arg)
|
||||||
|
{
|
||||||
|
#if defined(TARGET_MIPS64)
|
||||||
|
tcg_gen_ext32s_tl(s, ret, arg);
|
||||||
|
#else
|
||||||
|
tcg_gen_trunc_i64_tl(s, ret, arg);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static inline void check_cp0_enabled(DisasContext *ctx)
|
static inline void check_cp0_enabled(DisasContext *ctx)
|
||||||
{
|
{
|
||||||
if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
|
if (unlikely(!(ctx->hflags & MIPS_HFLAG_CP0)))
|
||||||
|
@ -4904,17 +4913,96 @@ static void gen_bshfl (DisasContext *ctx, uint32_t op2, int rt, int rd)
|
||||||
tcg_temp_free(tcg_ctx, t0);
|
tcg_temp_free(tcg_ctx, t0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
static void gen_lsa(DisasContext *ctx, int opc, int rd, int rs, int rt,
|
||||||
/* CP0 (MMU and control) */
|
int imm2)
|
||||||
static inline void gen_move_low32(TCGContext *s, TCGv ret, TCGv_i64 arg)
|
|
||||||
{
|
{
|
||||||
#if defined(TARGET_MIPS64)
|
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
|
||||||
tcg_gen_ext32s_tl(s, ret, arg);
|
TCGv **cpu_gpr = (TCGv **)tcg_ctx->cpu_gpr;
|
||||||
#else
|
TCGv t0;
|
||||||
tcg_gen_trunc_i64_tl(s, ret, arg);
|
TCGv t1;
|
||||||
#endif
|
if (rd == 0) {
|
||||||
|
/* Treat as NOP. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
t0 = tcg_temp_new(tcg_ctx);
|
||||||
|
t1 = tcg_temp_new(tcg_ctx);
|
||||||
|
gen_load_gpr(ctx, t0, rs);
|
||||||
|
gen_load_gpr(ctx, t1, rt);
|
||||||
|
tcg_gen_shli_tl(tcg_ctx, t0, t0, imm2 + 1);
|
||||||
|
tcg_gen_add_tl(tcg_ctx, *cpu_gpr[rd], t0, t1);
|
||||||
|
if (opc == OPC_LSA) {
|
||||||
|
tcg_gen_ext32s_tl(tcg_ctx, *cpu_gpr[rd], *cpu_gpr[rd]);
|
||||||
|
}
|
||||||
|
|
||||||
|
tcg_temp_free(tcg_ctx, t1);
|
||||||
|
tcg_temp_free(tcg_ctx, t0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void gen_align(DisasContext *ctx, int opc, int rd, int rs, int rt,
|
||||||
|
int bp)
|
||||||
|
{
|
||||||
|
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
|
||||||
|
TCGv **cpu_gpr = (TCGv **)tcg_ctx->cpu_gpr;
|
||||||
|
TCGv t0;
|
||||||
|
if (rd == 0) {
|
||||||
|
/* Treat as NOP. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
t0 = tcg_temp_new(tcg_ctx);
|
||||||
|
gen_load_gpr(ctx, t0, rt);
|
||||||
|
if (bp == 0) {
|
||||||
|
tcg_gen_mov_tl(tcg_ctx, *cpu_gpr[rd], t0);
|
||||||
|
} else {
|
||||||
|
TCGv t1 = tcg_temp_new(tcg_ctx);
|
||||||
|
gen_load_gpr(ctx, t1, rs);
|
||||||
|
switch (opc) {
|
||||||
|
case OPC_ALIGN:
|
||||||
|
{
|
||||||
|
TCGv_i64 t2 = tcg_temp_new_i64(tcg_ctx);
|
||||||
|
tcg_gen_concat_tl_i64(tcg_ctx, t2, t1, t0);
|
||||||
|
tcg_gen_shri_i64(tcg_ctx, t2, t2, 8 * (4 - bp));
|
||||||
|
gen_move_low32(tcg_ctx, *cpu_gpr[rd], t2);
|
||||||
|
tcg_temp_free_i64(tcg_ctx, t2);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OPC_DALIGN:
|
||||||
|
tcg_gen_shli_tl(tcg_ctx, t0, t0, 8 * bp);
|
||||||
|
tcg_gen_shri_tl(tcg_ctx, t1, t1, 8 * (8 - bp));
|
||||||
|
tcg_gen_or_tl(tcg_ctx, *cpu_gpr[rd], t1, t0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tcg_temp_free(tcg_ctx, t1);
|
||||||
|
}
|
||||||
|
|
||||||
|
tcg_temp_free(tcg_ctx, t0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void gen_bitswap(DisasContext *ctx, int opc, int rd, int rt)
|
||||||
|
{
|
||||||
|
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
|
||||||
|
TCGv **cpu_gpr = (TCGv **)tcg_ctx->cpu_gpr;
|
||||||
|
TCGv t0;
|
||||||
|
if (rd == 0) {
|
||||||
|
/* Treat as NOP. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
t0 = tcg_temp_new(tcg_ctx);
|
||||||
|
gen_load_gpr(ctx, t0, rt);
|
||||||
|
switch (opc) {
|
||||||
|
case OPC_BITSWAP:
|
||||||
|
gen_helper_bitswap(tcg_ctx, *cpu_gpr[rd], t0);
|
||||||
|
break;
|
||||||
|
#if defined(TARGET_MIPS64)
|
||||||
|
case OPC_DBITSWAP:
|
||||||
|
gen_helper_dbitswap(tcg_ctx, *cpu_gpr[rd], t0);
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
tcg_temp_free(tcg_ctx, t0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
/* CP0 (MMU and control) */
|
||||||
static inline void gen_mthc0_entrylo(TCGContext *s, TCGv arg, target_ulong off)
|
static inline void gen_mthc0_entrylo(TCGContext *s, TCGv arg, target_ulong off)
|
||||||
{
|
{
|
||||||
TCGv_i64 t0 = tcg_temp_new_i64(s);
|
TCGv_i64 t0 = tcg_temp_new_i64(s);
|
||||||
|
@ -16546,7 +16634,6 @@ out:
|
||||||
static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
|
static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
|
||||||
{
|
{
|
||||||
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
||||||
TCGv **cpu_gpr = (TCGv **)tcg_ctx->cpu_gpr;
|
|
||||||
int rs, rt, rd, sa;
|
int rs, rt, rd, sa;
|
||||||
uint32_t op1, op2;
|
uint32_t op1, op2;
|
||||||
|
|
||||||
|
@ -16558,18 +16645,7 @@ static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
|
||||||
op1 = MASK_SPECIAL(ctx->opcode);
|
op1 = MASK_SPECIAL(ctx->opcode);
|
||||||
switch (op1) {
|
switch (op1) {
|
||||||
case OPC_LSA:
|
case OPC_LSA:
|
||||||
if (rd != 0) {
|
gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
|
||||||
int imm2 = extract32(ctx->opcode, 6, 3);
|
|
||||||
TCGv t0 = tcg_temp_new(tcg_ctx);
|
|
||||||
TCGv t1 = tcg_temp_new(tcg_ctx);
|
|
||||||
gen_load_gpr(ctx, t0, rs);
|
|
||||||
gen_load_gpr(ctx, t1, rt);
|
|
||||||
tcg_gen_shli_tl(tcg_ctx, t0, t0, imm2 + 1);
|
|
||||||
tcg_gen_add_tl(tcg_ctx, t0, t0, t1);
|
|
||||||
tcg_gen_ext32s_tl(tcg_ctx, *cpu_gpr[rd], t0);
|
|
||||||
tcg_temp_free(tcg_ctx, t1);
|
|
||||||
tcg_temp_free(tcg_ctx, t0);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case OPC_MULT: case OPC_MULTU: case OPC_DIV: case OPC_DIVU:
|
case OPC_MULT: case OPC_MULTU: case OPC_DIV: case OPC_DIVU:
|
||||||
op2 = MASK_R6_MULDIV(ctx->opcode);
|
op2 = MASK_R6_MULDIV(ctx->opcode);
|
||||||
|
@ -16614,17 +16690,7 @@ static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
|
||||||
#if defined(TARGET_MIPS64)
|
#if defined(TARGET_MIPS64)
|
||||||
case OPC_DLSA:
|
case OPC_DLSA:
|
||||||
check_mips_64(ctx);
|
check_mips_64(ctx);
|
||||||
if (rd != 0) {
|
gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
|
||||||
int imm2 = extract32(ctx->opcode, 6, 3);
|
|
||||||
TCGv t0 = tcg_temp_new(tcg_ctx);
|
|
||||||
TCGv t1 = tcg_temp_new(tcg_ctx);
|
|
||||||
gen_load_gpr(ctx, t0, rs);
|
|
||||||
gen_load_gpr(ctx, t1, rt);
|
|
||||||
tcg_gen_shli_tl(tcg_ctx, t0, t0, imm2 + 1);
|
|
||||||
tcg_gen_add_tl(tcg_ctx, *cpu_gpr[rd], t0, t1);
|
|
||||||
tcg_temp_free(tcg_ctx, t1);
|
|
||||||
tcg_temp_free(tcg_ctx, t0);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case R6_OPC_DCLO:
|
case R6_OPC_DCLO:
|
||||||
case R6_OPC_DCLZ:
|
case R6_OPC_DCLZ:
|
||||||
|
@ -17044,40 +17110,20 @@ static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
|
||||||
break;
|
break;
|
||||||
case OPC_BSHFL:
|
case OPC_BSHFL:
|
||||||
{
|
{
|
||||||
TCGv t0;
|
|
||||||
if (rd == 0) {
|
if (rd == 0) {
|
||||||
/* Treat as NOP. */
|
/* Treat as NOP. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
t0 = tcg_temp_new(tcg_ctx);
|
|
||||||
gen_load_gpr(ctx, t0, rt);
|
|
||||||
|
|
||||||
op2 = MASK_BSHFL(ctx->opcode);
|
op2 = MASK_BSHFL(ctx->opcode);
|
||||||
switch (op2) {
|
switch (op2) {
|
||||||
case OPC_ALIGN: case OPC_ALIGN_END:
|
case OPC_ALIGN: case OPC_ALIGN_END:
|
||||||
sa &= 3;
|
gen_align(ctx, OPC_ALIGN, rd, rs, rt, sa & 3);
|
||||||
if (sa == 0) {
|
|
||||||
tcg_gen_mov_tl(tcg_ctx, *cpu_gpr[rd], t0);
|
|
||||||
} else {
|
|
||||||
TCGv t1 = tcg_temp_new(tcg_ctx);
|
|
||||||
TCGv_i64 t2 = tcg_temp_new_i64(tcg_ctx);
|
|
||||||
gen_load_gpr(ctx, t1, rs);
|
|
||||||
tcg_gen_concat_tl_i64(tcg_ctx, t2, t1, t0);
|
|
||||||
tcg_gen_shri_i64(tcg_ctx, t2, t2, 8 * (4 - sa));
|
|
||||||
#if defined(TARGET_MIPS64)
|
|
||||||
tcg_gen_ext32s_i64(tcg_ctx, *cpu_gpr[rd], t2);
|
|
||||||
#else
|
|
||||||
tcg_gen_extrl_i64_i32(tcg_ctx, *cpu_gpr[rd], t2);
|
|
||||||
#endif
|
|
||||||
tcg_temp_free_i64(tcg_ctx, t2);
|
|
||||||
tcg_temp_free(tcg_ctx, t1);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case OPC_BITSWAP:
|
case OPC_BITSWAP:
|
||||||
gen_helper_bitswap(tcg_ctx, *cpu_gpr[rd], t0);
|
gen_bitswap(ctx, op2, rd, rt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tcg_temp_free(tcg_ctx, t0);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#if defined(TARGET_MIPS64)
|
#if defined(TARGET_MIPS64)
|
||||||
|
@ -17090,34 +17136,20 @@ static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
|
||||||
case OPC_DBSHFL:
|
case OPC_DBSHFL:
|
||||||
check_mips_64(ctx);
|
check_mips_64(ctx);
|
||||||
{
|
{
|
||||||
TCGv t0;
|
|
||||||
if (rd == 0) {
|
if (rd == 0) {
|
||||||
/* Treat as NOP. */
|
/* Treat as NOP. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
t0 = tcg_temp_new(tcg_ctx);
|
|
||||||
gen_load_gpr(ctx, t0, rt);
|
|
||||||
|
|
||||||
op2 = MASK_DBSHFL(ctx->opcode);
|
op2 = MASK_DBSHFL(ctx->opcode);
|
||||||
switch (op2) {
|
switch (op2) {
|
||||||
case OPC_DALIGN: case OPC_DALIGN_END:
|
case OPC_DALIGN: case OPC_DALIGN_END:
|
||||||
sa &= 7;
|
gen_align(ctx, OPC_DALIGN, rd, rs, rt, sa & 7);
|
||||||
if (sa == 0) {
|
|
||||||
tcg_gen_mov_tl(tcg_ctx, *cpu_gpr[rd], t0);
|
|
||||||
} else {
|
|
||||||
TCGv t1 = tcg_temp_new(tcg_ctx);
|
|
||||||
gen_load_gpr(ctx, t1, rs);
|
|
||||||
tcg_gen_shli_tl(tcg_ctx, t0, t0, 8 * sa);
|
|
||||||
tcg_gen_shri_tl(tcg_ctx, t1, t1, 8 * (8 - sa));
|
|
||||||
tcg_gen_or_tl(tcg_ctx, *cpu_gpr[rd], t1, t0);
|
|
||||||
tcg_temp_free(tcg_ctx, t1);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case OPC_DBITSWAP:
|
case OPC_DBITSWAP:
|
||||||
gen_helper_dbitswap(tcg_ctx, *cpu_gpr[rd], t0);
|
gen_bitswap(ctx, op2, rd, rt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tcg_temp_free(tcg_ctx, t0);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue