target-mips: split decode_opc_special* into *_r6 and *_legacy

For better code readability and to avoid 'if' statements for all R6 and preR6
instructions whose opcodes are the same - decode_opc_special* functions are
split into functions with _r6 and _legacy suffixes.

*_r6 functions will contain instructions which were introduced in R6.
*_legacy functions will contain instructions which were removed in R6.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
Reviewed-by: Aurelien Jarno <aurelien@aurel32.net>
This commit is contained in:
Leon Alrae 2014-06-27 08:49:02 +01:00
parent 099e5b4d9f
commit 10dc65dbb8
1 changed files with 167 additions and 75 deletions

View File

@ -14482,6 +14482,70 @@ static void gen_mipsdsp_accinsn(DisasContext *ctx, uint32_t op1, uint32_t op2,
/* End MIPSDSP functions. */
static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
{
int rs, rt, rd;
uint32_t op1;
rs = (ctx->opcode >> 21) & 0x1f;
rt = (ctx->opcode >> 16) & 0x1f;
rd = (ctx->opcode >> 11) & 0x1f;
op1 = MASK_SPECIAL(ctx->opcode);
switch (op1) {
case OPC_SELEQZ:
case OPC_SELNEZ:
gen_cond_move(ctx, op1, rd, rs, rt);
break;
default: /* Invalid */
MIPS_INVAL("special_r6");
generate_exception(ctx, EXCP_RI);
break;
}
}
static void decode_opc_special_legacy(CPUMIPSState *env, DisasContext *ctx)
{
int rs, rt, rd;
uint32_t op1;
rs = (ctx->opcode >> 21) & 0x1f;
rt = (ctx->opcode >> 16) & 0x1f;
rd = (ctx->opcode >> 11) & 0x1f;
op1 = MASK_SPECIAL(ctx->opcode);
switch (op1) {
case OPC_MOVN: /* Conditional move */
case OPC_MOVZ:
check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
INSN_LOONGSON2E | INSN_LOONGSON2F);
gen_cond_move(ctx, op1, rd, rs, rt);
break;
case OPC_MFHI: /* Move from HI/LO */
case OPC_MFLO:
gen_HILO(ctx, op1, rs & 3, rd);
break;
case OPC_MTHI:
case OPC_MTLO: /* Move to HI/LO */
gen_HILO(ctx, op1, rd & 3, rs);
break;
case OPC_MOVCI:
check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
if (env->CP0_Config1 & (1 << CP0C1_FP)) {
check_cp1_enabled(ctx);
gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
(ctx->opcode >> 16) & 1);
} else {
generate_exception_err(ctx, EXCP_CpU, 1);
}
break;
default: /* Invalid */
MIPS_INVAL("special_legacy");
generate_exception(ctx, EXCP_RI);
break;
}
}
static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
{
int rs, rt, rd, sa;
@ -14514,18 +14578,6 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
break;
}
break;
case OPC_MOVN: /* Conditional move */
case OPC_MOVZ:
check_insn_opc_removed(ctx, ISA_MIPS32R6);
check_insn(ctx, ISA_MIPS4 | ISA_MIPS32 |
INSN_LOONGSON2E | INSN_LOONGSON2F);
gen_cond_move(ctx, op1, rd, rs, rt);
break;
case OPC_SELEQZ:
case OPC_SELNEZ:
check_insn(ctx, ISA_MIPS32R6);
gen_cond_move(ctx, op1, rd, rs, rt);
break;
case OPC_ADD ... OPC_SUBU:
gen_arith(ctx, op1, rd, rs, rt);
break;
@ -14580,16 +14632,6 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
case OPC_TNE:
gen_trap(ctx, op1, rs, rt, -1);
break;
case OPC_MFHI: /* Move from HI/LO */
case OPC_MFLO:
check_insn_opc_removed(ctx, ISA_MIPS32R6);
gen_HILO(ctx, op1, rs & 3, rd);
break;
case OPC_MTHI:
case OPC_MTLO: /* Move to HI/LO */
check_insn_opc_removed(ctx, ISA_MIPS32R6);
gen_HILO(ctx, op1, rd & 3, rs);
break;
case OPC_PMON: /* Pmon entry point, also R4010 selsl */
#ifdef MIPS_STRICT_STANDARD
MIPS_INVAL("PMON / selsl");
@ -14619,18 +14661,6 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
/* Treat as NOP. */
break;
case OPC_MOVCI:
check_insn_opc_removed(ctx, ISA_MIPS32R6);
check_insn(ctx, ISA_MIPS4 | ISA_MIPS32);
if (ctx->CP0_Config1 & (1 << CP0C1_FP)) {
check_cp1_enabled(ctx);
gen_movci(ctx, rd, rs, (ctx->opcode >> 18) & 0x7,
(ctx->opcode >> 16) & 1);
} else {
generate_exception_err(ctx, EXCP_CpU, 1);
}
break;
#if defined(TARGET_MIPS64)
/* MIPS64 specific opcodes */
case OPC_DSLL:
@ -14712,8 +14742,49 @@ static void decode_opc_special(CPUMIPSState *env, DisasContext *ctx)
gen_muldiv(ctx, op1, 0, rs, rt);
break;
#endif
default:
if (ctx->insn_flags & ISA_MIPS32R6) {
decode_opc_special_r6(env, ctx);
} else {
decode_opc_special_legacy(env, ctx);
}
}
}
static void decode_opc_special2_r6(CPUMIPSState *env, DisasContext *ctx)
{
uint32_t op1;
op1 = MASK_SPECIAL2(ctx->opcode);
switch (op1) {
default: /* Invalid */
MIPS_INVAL("special");
MIPS_INVAL("special2_r6");
generate_exception(ctx, EXCP_RI);
break;
}
}
static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
{
int rs, rt, rd;
uint32_t op1;
rs = (ctx->opcode >> 21) & 0x1f;
rt = (ctx->opcode >> 16) & 0x1f;
rd = (ctx->opcode >> 11) & 0x1f;
op1 = MASK_SPECIAL2(ctx->opcode);
switch (op1) {
case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
case OPC_MSUB ... OPC_MSUBU:
check_insn(ctx, ISA_MIPS32);
gen_muldiv(ctx, op1, rd & 3, rs, rt);
break;
case OPC_MUL:
gen_arith(ctx, op1, rd, rs, rt);
break;
default: /* Invalid */
MIPS_INVAL("special2_legacy");
generate_exception(ctx, EXCP_RI);
break;
}
@ -14730,16 +14801,6 @@ static void decode_opc_special2(CPUMIPSState *env, DisasContext *ctx)
op1 = MASK_SPECIAL2(ctx->opcode);
switch (op1) {
case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
case OPC_MSUB ... OPC_MSUBU:
check_insn_opc_removed(ctx, ISA_MIPS32R6);
check_insn(ctx, ISA_MIPS32);
gen_muldiv(ctx, op1, rd & 3, rs, rt);
break;
case OPC_MUL:
check_insn_opc_removed(ctx, ISA_MIPS32R6);
gen_arith(ctx, op1, rd, rs, rt);
break;
case OPC_CLO:
case OPC_CLZ:
check_insn(ctx, ISA_MIPS32);
@ -14783,30 +14844,78 @@ static void decode_opc_special2(CPUMIPSState *env, DisasContext *ctx)
gen_loongson_integer(ctx, op1, rd, rs, rt);
break;
#endif
default:
if (ctx->insn_flags & ISA_MIPS32R6) {
decode_opc_special2_r6(env, ctx);
} else {
decode_opc_special2_legacy(env, ctx);
}
}
}
static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
{
int rs, rt;
uint32_t op1;
int16_t imm;
rs = (ctx->opcode >> 21) & 0x1f;
rt = (ctx->opcode >> 16) & 0x1f;
imm = (int16_t)ctx->opcode >> 7;
op1 = MASK_SPECIAL3(ctx->opcode);
switch (op1) {
case R6_OPC_SC:
gen_st_cond(ctx, op1, rt, rs, imm);
break;
case R6_OPC_LL:
gen_ld(ctx, op1, rt, rs, imm);
break;
default: /* Invalid */
MIPS_INVAL("special2");
MIPS_INVAL("special3_r6");
generate_exception(ctx, EXCP_RI);
break;
}
}
static void decode_opc_special3_legacy(CPUMIPSState *env, DisasContext *ctx)
{
uint32_t op1;
#if defined(TARGET_MIPS64)
int rd = (ctx->opcode >> 11) & 0x1f;
int rs = (ctx->opcode >> 21) & 0x1f;
int rt = (ctx->opcode >> 16) & 0x1f;
#endif
op1 = MASK_SPECIAL3(ctx->opcode);
switch (op1) {
#if defined(TARGET_MIPS64)
case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
case OPC_DMOD_G_2E ... OPC_DMODU_G_2E:
check_insn(ctx, INSN_LOONGSON2E);
gen_loongson_integer(ctx, op1, rd, rs, rt);
break;
#endif
default: /* Invalid */
MIPS_INVAL("special3_legacy");
generate_exception(ctx, EXCP_RI);
break;
}
}
static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
{
int rs, rt, rd, sa;
uint32_t op1, op2;
int16_t imm;
rs = (ctx->opcode >> 21) & 0x1f;
rt = (ctx->opcode >> 16) & 0x1f;
rd = (ctx->opcode >> 11) & 0x1f;
sa = (ctx->opcode >> 6) & 0x1f;
imm = (int16_t)ctx->opcode;
op1 = MASK_SPECIAL3(ctx->opcode);
switch (op1) {
case R6_OPC_LL:
check_insn(ctx, ISA_MIPS32R6);
gen_ld(ctx, op1, rt, rs, imm >> 7);
break;
case OPC_EXT:
case OPC_INS:
check_insn(ctx, ISA_MIPS32R2);
@ -15111,19 +15220,6 @@ static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
break;
}
break;
case R6_OPC_SC: /* OPC_DMOD_G_2E */
if (ctx->insn_flags & ISA_MIPS32R6) {
gen_st_cond(ctx, op1, rt, rs, imm >> 7);
} else {
#if defined(TARGET_MIPS64)
check_insn(ctx, INSN_LOONGSON2E);
gen_loongson_integer(ctx, op1, rd, rs, rt);
#else
/* Invalid in MIPS32 */
generate_exception(ctx, EXCP_RI);
#endif
}
break;
#if defined(TARGET_MIPS64)
case OPC_DEXTM ... OPC_DEXT:
case OPC_DINSM ... OPC_DINS:
@ -15137,12 +15233,6 @@ static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
op2 = MASK_DBSHFL(ctx->opcode);
gen_bshfl(ctx, op2, rt, rd);
break;
case OPC_DDIV_G_2E ... OPC_DDIVU_G_2E:
case OPC_DMULT_G_2E ... OPC_DMULTU_G_2E:
case OPC_DMODU_G_2E:
check_insn(ctx, INSN_LOONGSON2E);
gen_loongson_integer(ctx, op1, rd, rs, rt);
break;
case OPC_ABSQ_S_QH_DSP:
op2 = MASK_ABSQ_S_QH(ctx->opcode);
switch (op2) {
@ -15374,10 +15464,12 @@ static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
gen_mipsdsp_shift(ctx, op1, rd, rs, rt);
break;
#endif
default: /* Invalid */
MIPS_INVAL("special3");
generate_exception(ctx, EXCP_RI);
break;
default:
if (ctx->insn_flags & ISA_MIPS32R6) {
decode_opc_special3_r6(env, ctx);
} else {
decode_opc_special3_legacy(env, ctx);
}
}
}