mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-22 23:11:03 +00:00
target/mips: Fix decoding mechanism of special R5900 opcodes
MOVN, MOVZ, MFHI, MFLO, MTHI, MTLO, MULT, MULTU, DIV, DIVU, DMULT, DMULTU, DDIV, DDIVU and JR are decoded in decode_opc_special_tx79 instead of the generic decode_opc_special_legacy. Backports commit 9dc324ce66807cc231fe890d4031de595ad1cf72 from qemu
This commit is contained in:
parent
f23c6fd006
commit
b671293fe0
|
@ -24019,6 +24019,53 @@ static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
|
|||
}
|
||||
}
|
||||
|
||||
static void decode_opc_special_tx79(CPUMIPSState *env, DisasContext *ctx)
|
||||
{
|
||||
int rs = extract32(ctx->opcode, 21, 5);
|
||||
int rt = extract32(ctx->opcode, 16, 5);
|
||||
int rd = extract32(ctx->opcode, 11, 5);
|
||||
uint32_t op1 = MASK_SPECIAL(ctx->opcode);
|
||||
|
||||
switch (op1) {
|
||||
case OPC_MOVN: /* Conditional move */
|
||||
case OPC_MOVZ:
|
||||
gen_cond_move(ctx, op1, rd, rs, rt);
|
||||
break;
|
||||
case OPC_MFHI: /* Move from HI/LO */
|
||||
case OPC_MFLO:
|
||||
gen_HILO(ctx, op1, 0, rd);
|
||||
break;
|
||||
case OPC_MTHI:
|
||||
case OPC_MTLO: /* Move to HI/LO */
|
||||
gen_HILO(ctx, op1, 0, rs);
|
||||
break;
|
||||
case OPC_MULT:
|
||||
case OPC_MULTU:
|
||||
gen_mul_txx9(ctx, op1, rd, rs, rt);
|
||||
break;
|
||||
case OPC_DIV:
|
||||
case OPC_DIVU:
|
||||
gen_muldiv(ctx, op1, 0, rs, rt);
|
||||
break;
|
||||
#if defined(TARGET_MIPS64)
|
||||
case OPC_DMULT:
|
||||
case OPC_DMULTU:
|
||||
case OPC_DDIV:
|
||||
case OPC_DDIVU:
|
||||
check_insn_opc_user_only(ctx, INSN_R5900);
|
||||
gen_muldiv(ctx, op1, 0, rs, rt);
|
||||
break;
|
||||
#endif
|
||||
case OPC_JR:
|
||||
gen_compute_branch(ctx, op1, 4, rs, 0, 0, 4);
|
||||
break;
|
||||
default: /* Invalid */
|
||||
MIPS_INVAL("special_tx79");
|
||||
generate_exception_end(ctx, EXCP_RI);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
|
||||
{
|
||||
int rs, rt, rd, sa;
|
||||
|
@ -24034,7 +24081,7 @@ static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
|
|||
case OPC_MOVN: /* Conditional move */
|
||||
case OPC_MOVZ:
|
||||
check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
|
||||
INSN_LOONGSON2E | INSN_LOONGSON2F | INSN_R5900);
|
||||
INSN_LOONGSON2E | INSN_LOONGSON2F);
|
||||
gen_cond_move(ctx, op1, rd, rs, rt);
|
||||
break;
|
||||
case OPC_MFHI: /* Move from HI/LO */
|
||||
|
@ -24061,8 +24108,6 @@ static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
|
|||
check_insn(ctx, INSN_VR54XX);
|
||||
op1 = MASK_MUL_VR54XX(ctx->opcode);
|
||||
gen_mul_vr54xx(ctx, op1, rd, rs, rt);
|
||||
} else if (ctx->insn_flags & INSN_R5900) {
|
||||
gen_mul_txx9(ctx, op1, rd, rs, rt);
|
||||
} else {
|
||||
gen_muldiv(ctx, op1, rd & 3, rs, rt);
|
||||
}
|
||||
|
@ -24077,7 +24122,6 @@ static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
|
|||
case OPC_DDIV:
|
||||
case OPC_DDIVU:
|
||||
check_insn(ctx, ISA_MIPS3);
|
||||
check_insn_opc_user_only(ctx, INSN_R5900);
|
||||
check_mips_64(ctx);
|
||||
gen_muldiv(ctx, op1, 0, rs, rt);
|
||||
break;
|
||||
|
@ -24305,6 +24349,8 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
|
|||
default:
|
||||
if (ctx->insn_flags & ISA_MIPS32R6) {
|
||||
decode_opc_special_r6(env, ctx);
|
||||
} else if (ctx->insn_flags & INSN_R5900) {
|
||||
decode_opc_special_tx79(env, ctx);
|
||||
} else {
|
||||
decode_opc_special_legacy(env, ctx);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue