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. Reviewed-by: Aleksandar Markovic <amarkovic@wavecomp.com> Signed-off-by: Fredrik Noring <noring@nocrew.org> Signed-off-by: Aleksandar Markovic <amarkovic@wavecomp.com>
This commit is contained in:
parent
c42171c3bf
commit
9dc324ce66
@ -23863,6 +23863,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;
|
||||
@ -23878,7 +23925,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 */
|
||||
@ -23905,8 +23952,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);
|
||||
}
|
||||
@ -23921,7 +23966,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;
|
||||
@ -24148,6 +24192,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 New Issue
Block a user