diff options
Diffstat (limited to 'target-mips/translate.c')
-rw-r--r-- | target-mips/translate.c | 228 |
1 files changed, 160 insertions, 68 deletions
diff --git a/target-mips/translate.c b/target-mips/translate.c index 5b8f762..0c64aeb 100644 --- a/target-mips/translate.c +++ b/target-mips/translate.c @@ -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,14 +14742,29 @@ 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(CPUMIPSState *env, DisasContext *ctx) +static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx) { int rs, rt, rd; uint32_t op1; @@ -14732,14 +14777,30 @@ static void decode_opc_special2(CPUMIPSState *env, DisasContext *ctx) 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; + default: /* Invalid */ + MIPS_INVAL("special2_legacy"); + generate_exception(ctx, EXCP_RI); + break; + } +} + +static void decode_opc_special2(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_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); + } } } |