mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-07-23 00:58:22 +00:00
target/mips/translate: Perform comparison pass with qemu
Keeps code and formatting in sync
This commit is contained in:
parent
7db1bff993
commit
95d50a02a1
|
@ -3175,6 +3175,7 @@ mips_symbols = (
|
||||||
'cpu_set_exception_base',
|
'cpu_set_exception_base',
|
||||||
'cpu_state_reset',
|
'cpu_state_reset',
|
||||||
'cpu_supports_isa',
|
'cpu_supports_isa',
|
||||||
|
'cpu_supports_cps_smp',
|
||||||
'cpu_wrdsp',
|
'cpu_wrdsp',
|
||||||
'do_raise_exception_err',
|
'do_raise_exception_err',
|
||||||
'exception_resume_pc',
|
'exception_resume_pc',
|
||||||
|
|
|
@ -3076,6 +3076,7 @@
|
||||||
#define cpu_set_exception_base cpu_set_exception_base_mips
|
#define cpu_set_exception_base cpu_set_exception_base_mips
|
||||||
#define cpu_state_reset cpu_state_reset_mips
|
#define cpu_state_reset cpu_state_reset_mips
|
||||||
#define cpu_supports_isa cpu_supports_isa_mips
|
#define cpu_supports_isa cpu_supports_isa_mips
|
||||||
|
#define cpu_supports_cps_smp cpu_supports_cps_smp_mips
|
||||||
#define cpu_wrdsp cpu_wrdsp_mips
|
#define cpu_wrdsp cpu_wrdsp_mips
|
||||||
#define do_raise_exception_err do_raise_exception_err_mips
|
#define do_raise_exception_err do_raise_exception_err_mips
|
||||||
#define exception_resume_pc exception_resume_pc_mips
|
#define exception_resume_pc exception_resume_pc_mips
|
||||||
|
|
|
@ -3076,6 +3076,7 @@
|
||||||
#define cpu_set_exception_base cpu_set_exception_base_mips64
|
#define cpu_set_exception_base cpu_set_exception_base_mips64
|
||||||
#define cpu_state_reset cpu_state_reset_mips64
|
#define cpu_state_reset cpu_state_reset_mips64
|
||||||
#define cpu_supports_isa cpu_supports_isa_mips64
|
#define cpu_supports_isa cpu_supports_isa_mips64
|
||||||
|
#define cpu_supports_cps_smp cpu_supports_cps_smp_mips64
|
||||||
#define cpu_wrdsp cpu_wrdsp_mips64
|
#define cpu_wrdsp cpu_wrdsp_mips64
|
||||||
#define do_raise_exception_err do_raise_exception_err_mips64
|
#define do_raise_exception_err do_raise_exception_err_mips64
|
||||||
#define exception_resume_pc exception_resume_pc_mips64
|
#define exception_resume_pc exception_resume_pc_mips64
|
||||||
|
|
|
@ -3076,6 +3076,7 @@
|
||||||
#define cpu_set_exception_base cpu_set_exception_base_mips64el
|
#define cpu_set_exception_base cpu_set_exception_base_mips64el
|
||||||
#define cpu_state_reset cpu_state_reset_mips64el
|
#define cpu_state_reset cpu_state_reset_mips64el
|
||||||
#define cpu_supports_isa cpu_supports_isa_mips64el
|
#define cpu_supports_isa cpu_supports_isa_mips64el
|
||||||
|
#define cpu_supports_cps_smp cpu_supports_cps_smp_mips64el
|
||||||
#define cpu_wrdsp cpu_wrdsp_mips64el
|
#define cpu_wrdsp cpu_wrdsp_mips64el
|
||||||
#define do_raise_exception_err do_raise_exception_err_mips64el
|
#define do_raise_exception_err do_raise_exception_err_mips64el
|
||||||
#define exception_resume_pc exception_resume_pc_mips64el
|
#define exception_resume_pc exception_resume_pc_mips64el
|
||||||
|
|
|
@ -3076,6 +3076,7 @@
|
||||||
#define cpu_set_exception_base cpu_set_exception_base_mipsel
|
#define cpu_set_exception_base cpu_set_exception_base_mipsel
|
||||||
#define cpu_state_reset cpu_state_reset_mipsel
|
#define cpu_state_reset cpu_state_reset_mipsel
|
||||||
#define cpu_supports_isa cpu_supports_isa_mipsel
|
#define cpu_supports_isa cpu_supports_isa_mipsel
|
||||||
|
#define cpu_supports_cps_smp cpu_supports_cps_smp_mipsel
|
||||||
#define cpu_wrdsp cpu_wrdsp_mipsel
|
#define cpu_wrdsp cpu_wrdsp_mipsel
|
||||||
#define do_raise_exception_err do_raise_exception_err_mipsel
|
#define do_raise_exception_err do_raise_exception_err_mipsel
|
||||||
#define exception_resume_pc exception_resume_pc_mipsel
|
#define exception_resume_pc exception_resume_pc_mipsel
|
||||||
|
|
|
@ -747,7 +747,8 @@ enum {
|
||||||
#define cpu_init(uc, cpu_model) cpu_generic_init(uc, TYPE_MIPS_CPU, cpu_model)
|
#define cpu_init(uc, cpu_model) cpu_generic_init(uc, TYPE_MIPS_CPU, cpu_model)
|
||||||
int cpu_mips_exec(struct uc_struct *uc, CPUState *cpu);
|
int cpu_mips_exec(struct uc_struct *uc, CPUState *cpu);
|
||||||
int cpu_mips_signal_handler(int host_signum, void *pinfo, void *puc);
|
int cpu_mips_signal_handler(int host_signum, void *pinfo, void *puc);
|
||||||
bool cpu_supports_isa(const char *cpu_model, unsigned int isa);
|
bool cpu_supports_isa(struct uc_struct *uc, const char *cpu_model, unsigned int isa);
|
||||||
|
bool cpu_supports_cps_smp(struct uc_struct *uc, const char *cpu_type);
|
||||||
void cpu_set_exception_base(struct uc_struct *uc, int vp_index, target_ulong address);
|
void cpu_set_exception_base(struct uc_struct *uc, int vp_index, target_ulong address);
|
||||||
|
|
||||||
/* mips_int.c */
|
/* mips_int.c */
|
||||||
|
|
|
@ -1470,7 +1470,7 @@ static const char * const regnames_LO[] = {
|
||||||
"LO0", "LO1", "LO2", "LO3",
|
"LO0", "LO1", "LO2", "LO3",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char * const fregnames[] = {
|
static QEMU_UNUSED_VAR const char * const fregnames[] = {
|
||||||
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
|
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
|
||||||
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
|
"f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
|
||||||
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
|
"f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
|
||||||
|
@ -1503,17 +1503,16 @@ static const char * const msaregnames[] = {
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define MIPS_INVAL(op) \
|
#define MIPS_INVAL(op) \
|
||||||
do { \
|
do { \
|
||||||
if (MIPS_DEBUG_DISAS) { \
|
if (MIPS_DEBUG_DISAS) { \
|
||||||
qemu_log_mask(CPU_LOG_TB_IN_ASM, \
|
qemu_log_mask(CPU_LOG_TB_IN_ASM, \
|
||||||
TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
|
TARGET_FMT_lx ": %08x Invalid %s %03x %03x %03x\n", \
|
||||||
ctx->pc, ctx->opcode, op, ctx->opcode >> 26, \
|
ctx->pc, ctx->opcode, op, ctx->opcode >> 26, \
|
||||||
ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
|
ctx->opcode & 0x3F, ((ctx->opcode >> 16) & 0x1F)); \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
/* General purpose registers moves. */
|
/* General purpose registers moves. */
|
||||||
static inline void gen_load_gpr (DisasContext *s, TCGv t, int reg)
|
static inline void gen_load_gpr (DisasContext *s, TCGv t, int reg)
|
||||||
{
|
{
|
||||||
|
@ -1655,7 +1654,7 @@ static void gen_load_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
|
||||||
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
|
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
|
||||||
|
|
||||||
if (ctx->hflags & MIPS_HFLAG_FRE) {
|
if (ctx->hflags & MIPS_HFLAG_FRE) {
|
||||||
generate_exception_end(ctx, EXCP_RI);
|
generate_exception(ctx, EXCP_RI);
|
||||||
}
|
}
|
||||||
tcg_gen_extrl_i64_i32(tcg_ctx, t, tcg_ctx->fpu_f64[reg]);
|
tcg_gen_extrl_i64_i32(tcg_ctx, t, tcg_ctx->fpu_f64[reg]);
|
||||||
}
|
}
|
||||||
|
@ -1665,7 +1664,7 @@ static void gen_store_fpr32(DisasContext *ctx, TCGv_i32 t, int reg)
|
||||||
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
|
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
|
||||||
TCGv_i64 t64;
|
TCGv_i64 t64;
|
||||||
if (ctx->hflags & MIPS_HFLAG_FRE) {
|
if (ctx->hflags & MIPS_HFLAG_FRE) {
|
||||||
generate_exception_end(ctx, EXCP_RI);
|
generate_exception(ctx, EXCP_RI);
|
||||||
}
|
}
|
||||||
t64 = tcg_temp_new_i64(tcg_ctx);
|
t64 = tcg_temp_new_i64(tcg_ctx);
|
||||||
tcg_gen_extu_i32_i64(tcg_ctx, t64, t);
|
tcg_gen_extu_i32_i64(tcg_ctx, t64, t);
|
||||||
|
@ -1677,10 +1676,7 @@ static void gen_load_fpr32h(DisasContext *ctx, TCGv_i32 t, int reg)
|
||||||
{
|
{
|
||||||
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
|
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
|
||||||
if (ctx->hflags & MIPS_HFLAG_F64) {
|
if (ctx->hflags & MIPS_HFLAG_F64) {
|
||||||
TCGv_i64 t64 = tcg_temp_new_i64(tcg_ctx);
|
tcg_gen_extrh_i64_i32(tcg_ctx, t, tcg_ctx->fpu_f64[reg]);
|
||||||
tcg_gen_shri_i64(tcg_ctx, t64, tcg_ctx->fpu_f64[reg], 32);
|
|
||||||
tcg_gen_extrl_i64_i32(tcg_ctx, t, t64);
|
|
||||||
tcg_temp_free_i64(tcg_ctx, t64);
|
|
||||||
} else {
|
} else {
|
||||||
gen_load_fpr32(ctx, t, reg | 1);
|
gen_load_fpr32(ctx, t, reg | 1);
|
||||||
}
|
}
|
||||||
|
@ -1759,12 +1755,23 @@ static target_long addr_add(DisasContext *ctx, target_long base,
|
||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Sign-extract the low 32-bits to a target_long. */
|
||||||
static inline void gen_move_low32(TCGContext *s, TCGv ret, TCGv_i64 arg)
|
static inline void gen_move_low32(TCGContext *s, TCGv ret, TCGv_i64 arg)
|
||||||
{
|
{
|
||||||
#if defined(TARGET_MIPS64)
|
#if defined(TARGET_MIPS64)
|
||||||
tcg_gen_ext32s_tl(s, ret, arg);
|
tcg_gen_ext32s_i64(s, ret, arg);
|
||||||
#else
|
#else
|
||||||
tcg_gen_trunc_i64_tl(s, ret, arg);
|
tcg_gen_extrl_i64_i32(s, ret, arg);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sign-extract the high 32-bits to a target_long. */
|
||||||
|
static inline void gen_move_high32(TCGContext *s, TCGv ret, TCGv_i64 arg)
|
||||||
|
{
|
||||||
|
#if defined(TARGET_MIPS64)
|
||||||
|
tcg_gen_sari_i64(s, ret, arg, 32);
|
||||||
|
#else
|
||||||
|
tcg_gen_extrh_i64_i32(s, ret, arg);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1866,7 +1873,7 @@ static inline void check_insn_opc_removed(DisasContext *ctx, int flags)
|
||||||
static inline void check_ps(DisasContext *ctx)
|
static inline void check_ps(DisasContext *ctx)
|
||||||
{
|
{
|
||||||
if (unlikely(!ctx->ps)) {
|
if (unlikely(!ctx->ps)) {
|
||||||
generate_exception_end(ctx, EXCP_RI);
|
generate_exception(ctx, EXCP_RI);
|
||||||
}
|
}
|
||||||
check_cp1_64bitmode(ctx);
|
check_cp1_64bitmode(ctx);
|
||||||
}
|
}
|
||||||
|
@ -1885,7 +1892,7 @@ static inline void check_mips_64(DisasContext *ctx)
|
||||||
static inline void check_mvh(DisasContext *ctx)
|
static inline void check_mvh(DisasContext *ctx)
|
||||||
{
|
{
|
||||||
if (unlikely(!ctx->mvh)) {
|
if (unlikely(!ctx->mvh)) {
|
||||||
generate_exception_end(ctx, EXCP_RI);
|
generate_exception(ctx, EXCP_RI);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -3598,12 +3605,9 @@ static void gen_muldiv(DisasContext *ctx, uint32_t opc,
|
||||||
tcg_gen_concat_tl_i64(tcg_ctx, t3, cpu_LO[acc], cpu_HI[acc]);
|
tcg_gen_concat_tl_i64(tcg_ctx, t3, cpu_LO[acc], cpu_HI[acc]);
|
||||||
tcg_gen_add_i64(tcg_ctx, t2, t2, t3);
|
tcg_gen_add_i64(tcg_ctx, t2, t2, t3);
|
||||||
tcg_temp_free_i64(tcg_ctx, t3);
|
tcg_temp_free_i64(tcg_ctx, t3);
|
||||||
tcg_gen_trunc_i64_tl(tcg_ctx, t0, t2);
|
gen_move_low32(tcg_ctx, cpu_LO[acc], t2);
|
||||||
tcg_gen_shri_i64(tcg_ctx, t2, t2, 32);
|
gen_move_high32(tcg_ctx, cpu_HI[acc], t2);
|
||||||
tcg_gen_trunc_i64_tl(tcg_ctx, t1, t2);
|
|
||||||
tcg_temp_free_i64(tcg_ctx, t2);
|
tcg_temp_free_i64(tcg_ctx, t2);
|
||||||
tcg_gen_ext32s_tl(tcg_ctx, cpu_LO[acc], t0);
|
|
||||||
tcg_gen_ext32s_tl(tcg_ctx, cpu_HI[acc], t1);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPC_MADDU:
|
case OPC_MADDU:
|
||||||
|
@ -3619,12 +3623,9 @@ static void gen_muldiv(DisasContext *ctx, uint32_t opc,
|
||||||
tcg_gen_concat_tl_i64(tcg_ctx, t3, cpu_LO[acc], cpu_HI[acc]);
|
tcg_gen_concat_tl_i64(tcg_ctx, t3, cpu_LO[acc], cpu_HI[acc]);
|
||||||
tcg_gen_add_i64(tcg_ctx, t2, t2, t3);
|
tcg_gen_add_i64(tcg_ctx, t2, t2, t3);
|
||||||
tcg_temp_free_i64(tcg_ctx, t3);
|
tcg_temp_free_i64(tcg_ctx, t3);
|
||||||
tcg_gen_trunc_i64_tl(tcg_ctx, t0, t2);
|
gen_move_low32(tcg_ctx, cpu_LO[acc], t2);
|
||||||
tcg_gen_shri_i64(tcg_ctx, t2, t2, 32);
|
gen_move_high32(tcg_ctx, cpu_HI[acc], t2);
|
||||||
tcg_gen_trunc_i64_tl(tcg_ctx, t1, t2);
|
|
||||||
tcg_temp_free_i64(tcg_ctx, t2);
|
tcg_temp_free_i64(tcg_ctx, t2);
|
||||||
tcg_gen_ext32s_tl(tcg_ctx, cpu_LO[acc], t0);
|
|
||||||
tcg_gen_ext32s_tl(tcg_ctx, cpu_HI[acc], t1);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPC_MSUB:
|
case OPC_MSUB:
|
||||||
|
@ -3638,12 +3639,9 @@ static void gen_muldiv(DisasContext *ctx, uint32_t opc,
|
||||||
tcg_gen_concat_tl_i64(tcg_ctx, t3, cpu_LO[acc], cpu_HI[acc]);
|
tcg_gen_concat_tl_i64(tcg_ctx, t3, cpu_LO[acc], cpu_HI[acc]);
|
||||||
tcg_gen_sub_i64(tcg_ctx, t2, t3, t2);
|
tcg_gen_sub_i64(tcg_ctx, t2, t3, t2);
|
||||||
tcg_temp_free_i64(tcg_ctx, t3);
|
tcg_temp_free_i64(tcg_ctx, t3);
|
||||||
tcg_gen_trunc_i64_tl(tcg_ctx, t0, t2);
|
gen_move_low32(tcg_ctx, cpu_LO[acc], t2);
|
||||||
tcg_gen_shri_i64(tcg_ctx, t2, t2, 32);
|
gen_move_high32(tcg_ctx, cpu_HI[acc], t2);
|
||||||
tcg_gen_trunc_i64_tl(tcg_ctx, t1, t2);
|
|
||||||
tcg_temp_free_i64(tcg_ctx, t2);
|
tcg_temp_free_i64(tcg_ctx, t2);
|
||||||
tcg_gen_ext32s_tl(tcg_ctx, cpu_LO[acc], t0);
|
|
||||||
tcg_gen_ext32s_tl(tcg_ctx, cpu_HI[acc], t1);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OPC_MSUBU:
|
case OPC_MSUBU:
|
||||||
|
@ -3659,12 +3657,9 @@ static void gen_muldiv(DisasContext *ctx, uint32_t opc,
|
||||||
tcg_gen_concat_tl_i64(tcg_ctx, t3, cpu_LO[acc], cpu_HI[acc]);
|
tcg_gen_concat_tl_i64(tcg_ctx, t3, cpu_LO[acc], cpu_HI[acc]);
|
||||||
tcg_gen_sub_i64(tcg_ctx, t2, t3, t2);
|
tcg_gen_sub_i64(tcg_ctx, t2, t3, t2);
|
||||||
tcg_temp_free_i64(tcg_ctx, t3);
|
tcg_temp_free_i64(tcg_ctx, t3);
|
||||||
tcg_gen_trunc_i64_tl(tcg_ctx, t0, t2);
|
gen_move_low32(tcg_ctx, cpu_LO[acc], t2);
|
||||||
tcg_gen_shri_i64(tcg_ctx, t2, t2, 32);
|
gen_move_high32(tcg_ctx, cpu_HI[acc], t2);
|
||||||
tcg_gen_trunc_i64_tl(tcg_ctx, t1, t2);
|
|
||||||
tcg_temp_free_i64(tcg_ctx, t2);
|
tcg_temp_free_i64(tcg_ctx, t2);
|
||||||
tcg_gen_ext32s_tl(tcg_ctx, cpu_LO[acc], t0);
|
|
||||||
tcg_gen_ext32s_tl(tcg_ctx, cpu_HI[acc], t1);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -4238,6 +4233,7 @@ static void gen_loongson_multimedia(DisasContext *ctx, int rd, int rs, int rt)
|
||||||
#undef LMI_DIRECT
|
#undef LMI_DIRECT
|
||||||
|
|
||||||
gen_store_fpr64(ctx, t0, rd);
|
gen_store_fpr64(ctx, t0, rd);
|
||||||
|
|
||||||
tcg_temp_free_i64(tcg_ctx, t0);
|
tcg_temp_free_i64(tcg_ctx, t0);
|
||||||
tcg_temp_free_i64(tcg_ctx, t1);
|
tcg_temp_free_i64(tcg_ctx, t1);
|
||||||
}
|
}
|
||||||
|
@ -4829,11 +4825,13 @@ static void gen_align(DisasContext *ctx, int opc, int rd, int rs, int rt,
|
||||||
tcg_temp_free_i64(tcg_ctx, t2);
|
tcg_temp_free_i64(tcg_ctx, t2);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
#if defined(TARGET_MIPS64)
|
||||||
case OPC_DALIGN:
|
case OPC_DALIGN:
|
||||||
tcg_gen_shli_tl(tcg_ctx, t0, t0, 8 * bp);
|
tcg_gen_shli_tl(tcg_ctx, t0, t0, 8 * bp);
|
||||||
tcg_gen_shri_tl(tcg_ctx, t1, t1, 8 * (8 - bp));
|
tcg_gen_shri_tl(tcg_ctx, t1, t1, 8 * (8 - bp));
|
||||||
tcg_gen_or_tl(tcg_ctx, cpu_gpr[rd], t1, t0);
|
tcg_gen_or_tl(tcg_ctx, cpu_gpr[rd], t1, t0);
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
tcg_temp_free(tcg_ctx, t1);
|
tcg_temp_free(tcg_ctx, t1);
|
||||||
}
|
}
|
||||||
|
@ -5199,7 +5197,6 @@ static void gen_mfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
||||||
TCGv_i64 tmp = tcg_temp_new_i64(tcg_ctx);
|
TCGv_i64 tmp = tcg_temp_new_i64(tcg_ctx);
|
||||||
tcg_gen_ld_i64(tcg_ctx, tmp, tcg_ctx->cpu_env,
|
tcg_gen_ld_i64(tcg_ctx, tmp, tcg_ctx->cpu_env,
|
||||||
offsetof(CPUMIPSState, CP0_EntryLo0));
|
offsetof(CPUMIPSState, CP0_EntryLo0));
|
||||||
|
|
||||||
#if defined(TARGET_MIPS64)
|
#if defined(TARGET_MIPS64)
|
||||||
if (ctx->rxi) {
|
if (ctx->rxi) {
|
||||||
/* Move RI/XI fields to bits 31:30 */
|
/* Move RI/XI fields to bits 31:30 */
|
||||||
|
@ -6144,12 +6141,12 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
||||||
case 0:
|
case 0:
|
||||||
save_cpu_state(ctx, 1);
|
save_cpu_state(ctx, 1);
|
||||||
gen_helper_mtc0_cause(tcg_ctx, tcg_ctx->cpu_env, arg);
|
gen_helper_mtc0_cause(tcg_ctx, tcg_ctx->cpu_env, arg);
|
||||||
rn = "Cause";
|
|
||||||
/* Stop translation as we may have triggered an interrupt. BS_STOP
|
/* Stop translation as we may have triggered an interrupt. BS_STOP
|
||||||
* isn't sufficient, we need to ensure we break out of translated
|
* isn't sufficient, we need to ensure we break out of translated
|
||||||
* code to check for pending interrupts. */
|
* code to check for pending interrupts. */
|
||||||
gen_save_pc(ctx, ctx->pc + 4);
|
gen_save_pc(ctx, ctx->pc + 4);
|
||||||
ctx->bstate = BS_EXCP;
|
ctx->bstate = BS_EXCP;
|
||||||
|
rn = "Cause";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto cp0_unimplemented;
|
goto cp0_unimplemented;
|
||||||
|
@ -6176,12 +6173,6 @@ static void gen_mtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
||||||
gen_helper_mtc0_ebase(tcg_ctx, tcg_ctx->cpu_env, arg);
|
gen_helper_mtc0_ebase(tcg_ctx, tcg_ctx->cpu_env, arg);
|
||||||
rn = "EBase";
|
rn = "EBase";
|
||||||
break;
|
break;
|
||||||
case 3:
|
|
||||||
check_insn(ctx, ISA_MIPS32R2);
|
|
||||||
CP0_CHECK(ctx->cmgcr);
|
|
||||||
tcg_gen_ld_tl(tcg_ctx, arg, tcg_ctx->cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
|
|
||||||
rn = "CMGCRBase";
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
goto cp0_unimplemented;
|
goto cp0_unimplemented;
|
||||||
}
|
}
|
||||||
|
@ -6862,6 +6853,12 @@ static void gen_dmfc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
||||||
tcg_gen_ld_tl(tcg_ctx, arg, tcg_ctx->cpu_env, offsetof(CPUMIPSState, CP0_EBase));
|
tcg_gen_ld_tl(tcg_ctx, arg, tcg_ctx->cpu_env, offsetof(CPUMIPSState, CP0_EBase));
|
||||||
rn = "EBase";
|
rn = "EBase";
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
|
check_insn(ctx, ISA_MIPS32R2);
|
||||||
|
CP0_CHECK(ctx->cmgcr);
|
||||||
|
tcg_gen_ld_tl(tcg_ctx, arg, tcg_ctx->cpu_env, offsetof(CPUMIPSState, CP0_CMGCRBase));
|
||||||
|
rn = "CMGCRBase";
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
goto cp0_unimplemented;
|
goto cp0_unimplemented;
|
||||||
}
|
}
|
||||||
|
@ -7305,7 +7302,6 @@ static void gen_dmtc0(DisasContext *ctx, TCGv arg, int reg, int sel)
|
||||||
// gen_helper_mtc0_contextconfig(tcg_ctx->cpu_env, arg); /* SmartMIPS ASE */
|
// gen_helper_mtc0_contextconfig(tcg_ctx->cpu_env, arg); /* SmartMIPS ASE */
|
||||||
rn = "ContextConfig";
|
rn = "ContextConfig";
|
||||||
goto cp0_unimplemented;
|
goto cp0_unimplemented;
|
||||||
// break;
|
|
||||||
case 2:
|
case 2:
|
||||||
CP0_CHECK(ctx->ulri);
|
CP0_CHECK(ctx->ulri);
|
||||||
tcg_gen_st_tl(tcg_ctx, arg, tcg_ctx->cpu_env,
|
tcg_gen_st_tl(tcg_ctx, arg, tcg_ctx->cpu_env,
|
||||||
|
@ -8374,8 +8370,6 @@ static void gen_cp0 (CPUMIPSState *env, DisasContext *ctx, uint32_t opc, int rt,
|
||||||
gen_helper_tlbr(tcg_ctx, tcg_ctx->cpu_env);
|
gen_helper_tlbr(tcg_ctx, tcg_ctx->cpu_env);
|
||||||
break;
|
break;
|
||||||
case OPC_ERET: /* OPC_ERETNC */
|
case OPC_ERET: /* OPC_ERETNC */
|
||||||
opn = "eret";
|
|
||||||
check_insn(ctx, ISA_MIPS2);
|
|
||||||
if ((ctx->insn_flags & ISA_MIPS32R6) &&
|
if ((ctx->insn_flags & ISA_MIPS32R6) &&
|
||||||
(ctx->hflags & MIPS_HFLAG_BMASK)) {
|
(ctx->hflags & MIPS_HFLAG_BMASK)) {
|
||||||
goto die;
|
goto die;
|
||||||
|
@ -10507,7 +10501,6 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
|
||||||
{
|
{
|
||||||
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
|
TCGContext *tcg_ctx = ctx->uc->tcg_ctx;
|
||||||
TCGv *cpu_gpr = tcg_ctx->cpu_gpr;
|
TCGv *cpu_gpr = tcg_ctx->cpu_gpr;
|
||||||
int store = 0;
|
|
||||||
TCGv t0 = tcg_temp_new(tcg_ctx);
|
TCGv t0 = tcg_temp_new(tcg_ctx);
|
||||||
|
|
||||||
if (base == 0) {
|
if (base == 0) {
|
||||||
|
@ -10560,7 +10553,6 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
|
||||||
tcg_gen_qemu_st_i32(ctx->uc, fp0, t0, ctx->mem_idx, MO_TEUL);
|
tcg_gen_qemu_st_i32(ctx->uc, fp0, t0, ctx->mem_idx, MO_TEUL);
|
||||||
tcg_temp_free_i32(tcg_ctx, fp0);
|
tcg_temp_free_i32(tcg_ctx, fp0);
|
||||||
}
|
}
|
||||||
store = 1;
|
|
||||||
break;
|
break;
|
||||||
case OPC_SDXC1:
|
case OPC_SDXC1:
|
||||||
check_cop1x(ctx);
|
check_cop1x(ctx);
|
||||||
|
@ -10571,7 +10563,6 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
|
||||||
tcg_gen_qemu_st_i64(ctx->uc, fp0, t0, ctx->mem_idx, MO_TEQ);
|
tcg_gen_qemu_st_i64(ctx->uc, fp0, t0, ctx->mem_idx, MO_TEQ);
|
||||||
tcg_temp_free_i64(tcg_ctx, fp0);
|
tcg_temp_free_i64(tcg_ctx, fp0);
|
||||||
}
|
}
|
||||||
store = 1;
|
|
||||||
break;
|
break;
|
||||||
case OPC_SUXC1:
|
case OPC_SUXC1:
|
||||||
check_cp1_64bitmode(ctx);
|
check_cp1_64bitmode(ctx);
|
||||||
|
@ -10582,7 +10573,6 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
|
||||||
tcg_gen_qemu_st_i64(ctx->uc, fp0, t0, ctx->mem_idx, MO_TEQ);
|
tcg_gen_qemu_st_i64(ctx->uc, fp0, t0, ctx->mem_idx, MO_TEQ);
|
||||||
tcg_temp_free_i64(tcg_ctx, fp0);
|
tcg_temp_free_i64(tcg_ctx, fp0);
|
||||||
}
|
}
|
||||||
store = 1;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tcg_temp_free(tcg_ctx, t0);
|
tcg_temp_free(tcg_ctx, t0);
|
||||||
|
@ -11437,8 +11427,8 @@ static void gen_mips16_save (DisasContext *ctx,
|
||||||
|
|
||||||
gen_load_gpr(ctx, t0, 29);
|
gen_load_gpr(ctx, t0, 29);
|
||||||
|
|
||||||
#define DECR_AND_STORE(reg) do { \
|
#define DECR_AND_STORE(reg) do { \
|
||||||
tcg_gen_movi_tl(tcg_ctx, t2, -4); \
|
tcg_gen_movi_tl(tcg_ctx, t2, -4); \
|
||||||
gen_op_addr_add(ctx, t0, t0, t2); \
|
gen_op_addr_add(ctx, t0, t0, t2); \
|
||||||
tcg_gen_qemu_st_tl(ctx->uc, t1, t0, ctx->mem_idx, MO_TEUL); \
|
tcg_gen_qemu_st_tl(ctx->uc, t1, t0, ctx->mem_idx, MO_TEUL); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
@ -11539,11 +11529,14 @@ static void gen_mips16_restore (DisasContext *ctx,
|
||||||
int astatic;
|
int astatic;
|
||||||
TCGv t0 = tcg_temp_new(tcg_ctx);
|
TCGv t0 = tcg_temp_new(tcg_ctx);
|
||||||
TCGv t1 = tcg_temp_new(tcg_ctx);
|
TCGv t1 = tcg_temp_new(tcg_ctx);
|
||||||
|
TCGv t2 = tcg_temp_new(tcg_ctx);
|
||||||
|
|
||||||
tcg_gen_addi_tl(tcg_ctx, t0, cpu_gpr[29], framesize);
|
tcg_gen_movi_tl(tcg_ctx, t2, framesize);
|
||||||
|
gen_op_addr_add(ctx, t0, cpu_gpr[29], t2);
|
||||||
|
|
||||||
#define DECR_AND_LOAD(reg) do { \
|
#define DECR_AND_LOAD(reg) do { \
|
||||||
tcg_gen_subi_tl(tcg_ctx, t0, t0, 4); \
|
tcg_gen_movi_tl(tcg_ctx, t2, -4); \
|
||||||
|
gen_op_addr_add(ctx, t0, t0, t2); \
|
||||||
tcg_gen_qemu_ld_tl(ctx->uc, t1, t0, ctx->mem_idx, MO_TESL); \
|
tcg_gen_qemu_ld_tl(ctx->uc, t1, t0, ctx->mem_idx, MO_TESL); \
|
||||||
gen_store_gpr(tcg_ctx, t1, reg); \
|
gen_store_gpr(tcg_ctx, t1, reg); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
@ -11627,9 +11620,11 @@ static void gen_mips16_restore (DisasContext *ctx,
|
||||||
}
|
}
|
||||||
#undef DECR_AND_LOAD
|
#undef DECR_AND_LOAD
|
||||||
|
|
||||||
tcg_gen_addi_tl(tcg_ctx, cpu_gpr[29], cpu_gpr[29], framesize);
|
tcg_gen_movi_tl(tcg_ctx, t2, framesize);
|
||||||
|
gen_op_addr_add(ctx, cpu_gpr[29], cpu_gpr[29], t2);
|
||||||
tcg_temp_free(tcg_ctx, t0);
|
tcg_temp_free(tcg_ctx, t0);
|
||||||
tcg_temp_free(tcg_ctx, t1);
|
tcg_temp_free(tcg_ctx, t1);
|
||||||
|
tcg_temp_free(tcg_ctx, t2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_addiupc (DisasContext *ctx, int rx, int imm,
|
static void gen_addiupc (DisasContext *ctx, int rx, int imm,
|
||||||
|
@ -12445,7 +12440,6 @@ enum {
|
||||||
POOL32S = 0x16, /* MIPS64 */
|
POOL32S = 0x16, /* MIPS64 */
|
||||||
DADDIU32 = 0x17, /* MIPS64 */
|
DADDIU32 = 0x17, /* MIPS64 */
|
||||||
|
|
||||||
/* 0x1f is reserved */
|
|
||||||
POOL32C = 0x18,
|
POOL32C = 0x18,
|
||||||
LWGP16 = 0x19,
|
LWGP16 = 0x19,
|
||||||
LW16 = 0x1a,
|
LW16 = 0x1a,
|
||||||
|
@ -13700,10 +13694,8 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
|
||||||
save_cpu_state(ctx, 1);
|
save_cpu_state(ctx, 1);
|
||||||
gen_helper_di(tcg_ctx, t0, tcg_ctx->cpu_env);
|
gen_helper_di(tcg_ctx, t0, tcg_ctx->cpu_env);
|
||||||
gen_store_gpr(tcg_ctx, t0, rs);
|
gen_store_gpr(tcg_ctx, t0, rs);
|
||||||
/* BS_STOP isn't sufficient, we need to ensure we break out
|
/* Stop translation as we may have switched the execution mode */
|
||||||
of translated code to check for pending interrupts. */
|
ctx->bstate = BS_STOP;
|
||||||
gen_save_pc(ctx, ctx->pc + 4);
|
|
||||||
ctx->bstate = BS_EXCP;
|
|
||||||
tcg_temp_free(tcg_ctx, t0);
|
tcg_temp_free(tcg_ctx, t0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -13715,8 +13707,10 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
|
||||||
save_cpu_state(ctx, 1);
|
save_cpu_state(ctx, 1);
|
||||||
gen_helper_ei(tcg_ctx, t0, tcg_ctx->cpu_env);
|
gen_helper_ei(tcg_ctx, t0, tcg_ctx->cpu_env);
|
||||||
gen_store_gpr(tcg_ctx, t0, rs);
|
gen_store_gpr(tcg_ctx, t0, rs);
|
||||||
/* Stop translation as we may have switched the execution mode */
|
/* BS_STOP isn't sufficient, we need to ensure we break out
|
||||||
ctx->bstate = BS_STOP;
|
of translated code to check for pending interrupts. */
|
||||||
|
gen_save_pc(ctx, ctx->pc + 4);
|
||||||
|
ctx->bstate = BS_EXCP;
|
||||||
tcg_temp_free(tcg_ctx, t0);
|
tcg_temp_free(tcg_ctx, t0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -13732,7 +13726,6 @@ static void gen_pool32axf (CPUMIPSState *env, DisasContext *ctx, int rt, int rs)
|
||||||
break;
|
break;
|
||||||
case SYSCALL:
|
case SYSCALL:
|
||||||
generate_exception_end(ctx, EXCP_SYSCALL);
|
generate_exception_end(ctx, EXCP_SYSCALL);
|
||||||
ctx->bstate = BS_STOP;
|
|
||||||
break;
|
break;
|
||||||
case SDBBP:
|
case SDBBP:
|
||||||
check_insn(ctx, ISA_MIPS32);
|
check_insn(ctx, ISA_MIPS32);
|
||||||
|
@ -15469,7 +15462,6 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, bool *ins
|
||||||
opc = OPC_SUBU;
|
opc = OPC_SUBU;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->insn_flags & ISA_MIPS32R6) {
|
if (ctx->insn_flags & ISA_MIPS32R6) {
|
||||||
/* In the Release 6 the register number location in
|
/* In the Release 6 the register number location in
|
||||||
* the instruction encoding has changed.
|
* the instruction encoding has changed.
|
||||||
|
@ -15643,6 +15635,7 @@ static int decode_micromips_opc (CPUMIPSState *env, DisasContext *ctx, bool *ins
|
||||||
mmreg(uMIPS_RD(ctx->opcode)),
|
mmreg(uMIPS_RD(ctx->opcode)),
|
||||||
0, sextract32(ctx->opcode, 0, 7) << 1,
|
0, sextract32(ctx->opcode, 0, 7) << 1,
|
||||||
(ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
|
(ctx->insn_flags & ISA_MIPS32R6) ? 0 : 4);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
case LI16:
|
case LI16:
|
||||||
{
|
{
|
||||||
|
@ -17373,63 +17366,13 @@ static void decode_opc_special_r6(CPUMIPSState *env, DisasContext *ctx)
|
||||||
{
|
{
|
||||||
int rs, rt, rd, sa;
|
int rs, rt, rd, sa;
|
||||||
uint32_t op1, op2;
|
uint32_t op1, op2;
|
||||||
int16_t imm;
|
|
||||||
|
|
||||||
rs = (ctx->opcode >> 21) & 0x1f;
|
rs = (ctx->opcode >> 21) & 0x1f;
|
||||||
rt = (ctx->opcode >> 16) & 0x1f;
|
rt = (ctx->opcode >> 16) & 0x1f;
|
||||||
rd = (ctx->opcode >> 11) & 0x1f;
|
rd = (ctx->opcode >> 11) & 0x1f;
|
||||||
sa = (ctx->opcode >> 6) & 0x1f;
|
sa = (ctx->opcode >> 6) & 0x1f;
|
||||||
imm = sextract32(ctx->opcode, 7, 9);
|
|
||||||
|
|
||||||
op1 = MASK_SPECIAL(ctx->opcode);
|
op1 = MASK_SPECIAL(ctx->opcode);
|
||||||
|
|
||||||
/*
|
|
||||||
* EVA loads and stores overlap Loongson 2E instructions decoded by
|
|
||||||
* decode_opc_special3_legacy(), so be careful to allow their decoding when
|
|
||||||
* EVA is absent.
|
|
||||||
*/
|
|
||||||
if (ctx->eva) {
|
|
||||||
switch (op1) {
|
|
||||||
case OPC_LWLE:
|
|
||||||
case OPC_LWRE:
|
|
||||||
check_insn_opc_removed(ctx, ISA_MIPS32R6);
|
|
||||||
/* fall through */
|
|
||||||
case OPC_LBUE:
|
|
||||||
case OPC_LHUE:
|
|
||||||
case OPC_LBE:
|
|
||||||
case OPC_LHE:
|
|
||||||
case OPC_LLE:
|
|
||||||
case OPC_LWE:
|
|
||||||
check_cp0_enabled(ctx);
|
|
||||||
gen_ld(ctx, op1, rt, rs, imm);
|
|
||||||
return;
|
|
||||||
case OPC_SWLE ... OPC_SWRE:
|
|
||||||
check_insn_opc_removed(ctx, ISA_MIPS32R6);
|
|
||||||
/* fall through */
|
|
||||||
case OPC_SBE:
|
|
||||||
case OPC_SHE:
|
|
||||||
case OPC_SWE:
|
|
||||||
check_cp0_enabled(ctx);
|
|
||||||
gen_st(ctx, op1, rt, rs, imm);
|
|
||||||
return;
|
|
||||||
case OPC_SCE:
|
|
||||||
check_cp0_enabled(ctx);
|
|
||||||
gen_st_cond(ctx, op1, rt, rs, imm);
|
|
||||||
return;
|
|
||||||
case OPC_CACHEE:
|
|
||||||
check_cp0_enabled(ctx);
|
|
||||||
if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
|
|
||||||
gen_cache_operation(ctx, rt, rs, imm);
|
|
||||||
}
|
|
||||||
/* Treat as NOP. */
|
|
||||||
return;
|
|
||||||
case OPC_PREFE:
|
|
||||||
check_cp0_enabled(ctx);
|
|
||||||
/* Treat as NOP. */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (op1) {
|
switch (op1) {
|
||||||
case OPC_LSA:
|
case OPC_LSA:
|
||||||
gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
|
gen_lsa(ctx, op1, rd, rs, rt, extract32(ctx->opcode, 6, 2));
|
||||||
|
@ -17807,7 +17750,7 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
|
||||||
|
|
||||||
op1 = MASK_SPECIAL2(ctx->opcode);
|
op1 = MASK_SPECIAL2(ctx->opcode);
|
||||||
switch (op1) {
|
switch (op1) {
|
||||||
case OPC_MADD: case OPC_MADDU:
|
case OPC_MADD: case OPC_MADDU: /* Multiply and add/sub */
|
||||||
case OPC_MSUB: case OPC_MSUBU:
|
case OPC_MSUB: case OPC_MSUBU:
|
||||||
check_insn(ctx, ISA_MIPS32);
|
check_insn(ctx, ISA_MIPS32);
|
||||||
gen_muldiv(ctx, op1, rd & 3, rs, rt);
|
gen_muldiv(ctx, op1, rd & 3, rs, rt);
|
||||||
|
@ -17835,7 +17778,6 @@ static void decode_opc_special2_legacy(CPUMIPSState *env, DisasContext *ctx)
|
||||||
*/
|
*/
|
||||||
check_insn(ctx, ISA_MIPS32);
|
check_insn(ctx, ISA_MIPS32);
|
||||||
generate_exception_end(ctx, EXCP_DBp);
|
generate_exception_end(ctx, EXCP_DBp);
|
||||||
/* Treat as NOP. */
|
|
||||||
break;
|
break;
|
||||||
#if defined(TARGET_MIPS64)
|
#if defined(TARGET_MIPS64)
|
||||||
case OPC_DCLO:
|
case OPC_DCLO:
|
||||||
|
@ -17900,7 +17842,6 @@ static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
|
||||||
/* Treat as NOP. */
|
/* Treat as NOP. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
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:
|
||||||
|
@ -17926,7 +17867,6 @@ static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
|
||||||
/* Treat as NOP. */
|
/* Treat as NOP. */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
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:
|
||||||
|
@ -17936,6 +17876,7 @@ static void decode_opc_special3_r6(CPUMIPSState *env, DisasContext *ctx)
|
||||||
gen_bitswap(ctx, op2, rd, rt);
|
gen_bitswap(ctx, op2, rd, rt);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
@ -18473,13 +18414,57 @@ static void decode_opc_special3(CPUMIPSState *env, DisasContext *ctx)
|
||||||
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
TCGContext *tcg_ctx = env->uc->tcg_ctx;
|
||||||
int rs, rt, rd, sa;
|
int rs, rt, rd, sa;
|
||||||
uint32_t op1, op2;
|
uint32_t op1, op2;
|
||||||
|
int16_t imm;
|
||||||
|
|
||||||
rs = (ctx->opcode >> 21) & 0x1f;
|
rs = (ctx->opcode >> 21) & 0x1f;
|
||||||
rt = (ctx->opcode >> 16) & 0x1f;
|
rt = (ctx->opcode >> 16) & 0x1f;
|
||||||
rd = (ctx->opcode >> 11) & 0x1f;
|
rd = (ctx->opcode >> 11) & 0x1f;
|
||||||
sa = (ctx->opcode >> 6) & 0x1f;
|
sa = (ctx->opcode >> 6) & 0x1f;
|
||||||
|
imm = sextract32(ctx->opcode, 7, 9);
|
||||||
|
|
||||||
op1 = MASK_SPECIAL3(ctx->opcode);
|
op1 = MASK_SPECIAL3(ctx->opcode);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* EVA loads and stores overlap Loongson 2E instructions decoded by
|
||||||
|
* decode_opc_special3_legacy(), so be careful to allow their decoding when
|
||||||
|
* EVA is absent.
|
||||||
|
*/
|
||||||
|
if (ctx->eva) {
|
||||||
|
switch (op1) {
|
||||||
|
case OPC_LWLE: case OPC_LWRE:
|
||||||
|
check_insn_opc_removed(ctx, ISA_MIPS32R6);
|
||||||
|
/* fall through */
|
||||||
|
case OPC_LBUE: case OPC_LHUE:
|
||||||
|
case OPC_LBE: case OPC_LHE: case OPC_LLE: case OPC_LWE:
|
||||||
|
check_cp0_enabled(ctx);
|
||||||
|
gen_ld(ctx, op1, rt, rs, imm);
|
||||||
|
return;
|
||||||
|
case OPC_SWLE: case OPC_SWRE:
|
||||||
|
check_insn_opc_removed(ctx, ISA_MIPS32R6);
|
||||||
|
/* fall through */
|
||||||
|
case OPC_SBE: case OPC_SHE:
|
||||||
|
case OPC_SWE:
|
||||||
|
check_cp0_enabled(ctx);
|
||||||
|
gen_st(ctx, op1, rt, rs, imm);
|
||||||
|
return;
|
||||||
|
case OPC_SCE:
|
||||||
|
check_cp0_enabled(ctx);
|
||||||
|
gen_st_cond(ctx, op1, rt, rs, imm);
|
||||||
|
return;
|
||||||
|
case OPC_CACHEE:
|
||||||
|
check_cp0_enabled(ctx);
|
||||||
|
if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
|
||||||
|
gen_cache_operation(ctx, rt, rs, imm);
|
||||||
|
}
|
||||||
|
/* Treat as NOP. */
|
||||||
|
return;
|
||||||
|
case OPC_PREFE:
|
||||||
|
check_cp0_enabled(ctx);
|
||||||
|
/* Treat as NOP. */
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (op1) {
|
switch (op1) {
|
||||||
case OPC_EXT:
|
case OPC_EXT:
|
||||||
case OPC_INS:
|
case OPC_INS:
|
||||||
|
@ -19826,6 +19811,8 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx, bool *insn_need_pat
|
||||||
case OPC_MTC0:
|
case OPC_MTC0:
|
||||||
case OPC_MFTR:
|
case OPC_MFTR:
|
||||||
case OPC_MTTR:
|
case OPC_MTTR:
|
||||||
|
case OPC_MFHC0:
|
||||||
|
case OPC_MTHC0:
|
||||||
#if defined(TARGET_MIPS64)
|
#if defined(TARGET_MIPS64)
|
||||||
case OPC_DMFC0:
|
case OPC_DMFC0:
|
||||||
case OPC_DMTC0:
|
case OPC_DMTC0:
|
||||||
|
@ -19887,7 +19874,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx, bool *insn_need_pat
|
||||||
gen_helper_di(tcg_ctx, t0, tcg_ctx->cpu_env);
|
gen_helper_di(tcg_ctx, t0, tcg_ctx->cpu_env);
|
||||||
gen_store_gpr(tcg_ctx, t0, rt);
|
gen_store_gpr(tcg_ctx, t0, rt);
|
||||||
/* Stop translation as we may have switched
|
/* Stop translation as we may have switched
|
||||||
the execution mode */
|
the execution mode. */
|
||||||
ctx->bstate = BS_STOP;
|
ctx->bstate = BS_STOP;
|
||||||
break;
|
break;
|
||||||
case OPC_EI:
|
case OPC_EI:
|
||||||
|
@ -20000,7 +19987,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx, bool *insn_need_pat
|
||||||
case OPC_BEQL:
|
case OPC_BEQL:
|
||||||
case OPC_BNEL:
|
case OPC_BNEL:
|
||||||
check_insn(ctx, ISA_MIPS2);
|
check_insn(ctx, ISA_MIPS2);
|
||||||
check_insn_opc_removed(ctx, ISA_MIPS32R6);
|
check_insn_opc_removed(ctx, ISA_MIPS32R6);
|
||||||
/* Fallthrough */
|
/* Fallthrough */
|
||||||
case OPC_BEQ:
|
case OPC_BEQ:
|
||||||
case OPC_BNE:
|
case OPC_BNE:
|
||||||
|
@ -20027,9 +20014,9 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx, bool *insn_need_pat
|
||||||
break;
|
break;
|
||||||
case OPC_SC:
|
case OPC_SC:
|
||||||
check_insn(ctx, ISA_MIPS2);
|
check_insn(ctx, ISA_MIPS2);
|
||||||
check_insn_opc_removed(ctx, ISA_MIPS32R6);
|
check_insn_opc_removed(ctx, ISA_MIPS32R6);
|
||||||
gen_st_cond(ctx, op, rt, rs, imm);
|
gen_st_cond(ctx, op, rt, rs, imm);
|
||||||
break;
|
break;
|
||||||
case OPC_CACHE:
|
case OPC_CACHE:
|
||||||
check_insn_opc_removed(ctx, ISA_MIPS32R6);
|
check_insn_opc_removed(ctx, ISA_MIPS32R6);
|
||||||
check_cp0_enabled(ctx);
|
check_cp0_enabled(ctx);
|
||||||
|
@ -20037,6 +20024,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx, bool *insn_need_pat
|
||||||
if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
|
if (ctx->hflags & MIPS_HFLAG_ITC_CACHE) {
|
||||||
gen_cache_operation(ctx, rt, rs, imm);
|
gen_cache_operation(ctx, rt, rs, imm);
|
||||||
}
|
}
|
||||||
|
/* Treat as NOP. */
|
||||||
break;
|
break;
|
||||||
case OPC_PREF:
|
case OPC_PREF:
|
||||||
check_insn_opc_removed(ctx, ISA_MIPS32R6);
|
check_insn_opc_removed(ctx, ISA_MIPS32R6);
|
||||||
|
@ -20114,8 +20102,8 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx, bool *insn_need_pat
|
||||||
case OPC_S_FMT:
|
case OPC_S_FMT:
|
||||||
case OPC_D_FMT:
|
case OPC_D_FMT:
|
||||||
check_cp1_enabled(ctx);
|
check_cp1_enabled(ctx);
|
||||||
gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
|
gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
|
||||||
rt, rd, sa, (imm >> 8) & 0x7);
|
(imm >> 8) & 0x7);
|
||||||
break;
|
break;
|
||||||
case OPC_W_FMT:
|
case OPC_W_FMT:
|
||||||
case OPC_L_FMT:
|
case OPC_L_FMT:
|
||||||
|
@ -20173,8 +20161,9 @@ static void decode_opc(CPUMIPSState *env, DisasContext *ctx, bool *insn_need_pat
|
||||||
gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
|
gen_r6_cmp_d(ctx, ctx->opcode & 0x1f, rt, rd, sa);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f), rt, rd, sa,
|
gen_farith(ctx, ctx->opcode & FOP(0x3f, 0x1f),
|
||||||
(imm >> 8) & 0x7);
|
rt, rd, sa, (imm >> 8) & 0x7);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -20539,7 +20528,7 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
|
||||||
|
|
||||||
if (ctx.hflags & MIPS_HFLAG_BMASK) {
|
if (ctx.hflags & MIPS_HFLAG_BMASK) {
|
||||||
if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
|
if (!(ctx.hflags & (MIPS_HFLAG_BDS16 | MIPS_HFLAG_BDS32 |
|
||||||
MIPS_HFLAG_FBNSLOT))) {
|
MIPS_HFLAG_FBNSLOT))) {
|
||||||
/* force to generate branch as there is neither delay nor
|
/* force to generate branch as there is neither delay nor
|
||||||
forbidden slot */
|
forbidden slot */
|
||||||
is_slot = 1;
|
is_slot = 1;
|
||||||
|
@ -20551,7 +20540,6 @@ void gen_intermediate_code(CPUState *cs, struct TranslationBlock *tb)
|
||||||
is_slot = 1;
|
is_slot = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_slot) {
|
if (is_slot) {
|
||||||
gen_branch(&ctx, insn_bytes);
|
gen_branch(&ctx, insn_bytes);
|
||||||
}
|
}
|
||||||
|
@ -20735,14 +20723,16 @@ void cpu_mips_realize_env(CPUMIPSState *env)
|
||||||
mvp_init(env, env->cpu_model);
|
mvp_init(env, env->cpu_model);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cpu_supports_isa(const char *cpu_model, unsigned int isa)
|
bool cpu_supports_cps_smp(struct uc_struct *uc, const char *cpu_type)
|
||||||
{
|
{
|
||||||
const mips_def_t *def = cpu_mips_find_by_name(cpu_model);
|
const MIPSCPUClass *mcc = MIPS_CPU_CLASS(uc, object_class_by_name(uc, cpu_type));
|
||||||
if (!def) {
|
return (mcc->cpu_def->CP0_Config3 & (1 << CP0C3_CMGCR)) != 0;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return (def->insn_flags & isa) != 0;
|
bool cpu_supports_isa(struct uc_struct *uc, const char *cpu_type, unsigned int isa)
|
||||||
|
{
|
||||||
|
const MIPSCPUClass *mcc = MIPS_CPU_CLASS(uc, object_class_by_name(uc, cpu_type));
|
||||||
|
return (mcc->cpu_def->insn_flags & isa) != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void cpu_set_exception_base(struct uc_struct *uc, int vp_index, target_ulong address)
|
void cpu_set_exception_base(struct uc_struct *uc, int vp_index, target_ulong address)
|
||||||
|
|
|
@ -1046,18 +1046,6 @@ const mips_def_t mips_defs[] =
|
||||||
};
|
};
|
||||||
const int mips_defs_number = ARRAY_SIZE(mips_defs);
|
const int mips_defs_number = ARRAY_SIZE(mips_defs);
|
||||||
|
|
||||||
static const mips_def_t *cpu_mips_find_by_name (const char *name)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(mips_defs); i++) {
|
|
||||||
if (strcasecmp(name, mips_defs[i].name) == 0) {
|
|
||||||
return &mips_defs[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf)
|
void mips_cpu_list (FILE *f, fprintf_function cpu_fprintf)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
|
Loading…
Reference in a new issue