Per-CPU instruction decoding implementation, by Aurelien Jarno.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3228 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
92a34c10b5
commit
e189e74868
@ -441,6 +441,7 @@ struct CPUMIPSState {
|
||||
int CCRes; /* Cycle count resolution/divisor */
|
||||
uint32_t CP0_Status_rw_bitmask; /* Read/write bits in CP0_Status */
|
||||
uint32_t CP0_TCStatus_rw_bitmask; /* Read/write bits in CP0_TCStatus */
|
||||
int insn_flags; /* Supported instruction set */
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
target_ulong tls_value;
|
||||
|
@ -369,8 +369,7 @@ void do_interrupt (CPUState *env)
|
||||
}
|
||||
enter_debug_mode:
|
||||
env->hflags |= MIPS_HFLAG_DM;
|
||||
if ((env->CP0_Config0 & (0x3 << CP0C0_AT)))
|
||||
env->hflags |= MIPS_HFLAG_64;
|
||||
env->hflags |= MIPS_HFLAG_64;
|
||||
env->hflags &= ~MIPS_HFLAG_UM;
|
||||
/* EJTAG probe trap enable is not implemented... */
|
||||
if (!(env->CP0_Status & (1 << CP0St_EXL)))
|
||||
@ -396,8 +395,7 @@ void do_interrupt (CPUState *env)
|
||||
env->CP0_ErrorEPC = env->PC[env->current_tc];
|
||||
}
|
||||
env->CP0_Status |= (1 << CP0St_ERL) | (1 << CP0St_BEV);
|
||||
if ((env->CP0_Config0 & (0x3 << CP0C0_AT)))
|
||||
env->hflags |= MIPS_HFLAG_64;
|
||||
env->hflags |= MIPS_HFLAG_64;
|
||||
env->hflags &= ~MIPS_HFLAG_UM;
|
||||
if (!(env->CP0_Status & (1 << CP0St_EXL)))
|
||||
env->CP0_Cause &= ~(1 << CP0Ca_BD);
|
||||
@ -499,8 +497,7 @@ void do_interrupt (CPUState *env)
|
||||
env->CP0_Cause &= ~(1 << CP0Ca_BD);
|
||||
}
|
||||
env->CP0_Status |= (1 << CP0St_EXL);
|
||||
if ((env->CP0_Config0 & (0x3 << CP0C0_AT)))
|
||||
env->hflags |= MIPS_HFLAG_64;
|
||||
env->hflags |= MIPS_HFLAG_64;
|
||||
env->hflags &= ~MIPS_HFLAG_UM;
|
||||
}
|
||||
env->hflags &= ~MIPS_HFLAG_BMASK;
|
||||
|
@ -14,6 +14,41 @@
|
||||
#define TARGET_LONG_BITS 32
|
||||
#endif
|
||||
|
||||
/* Masks used to mark instructions to indicate which ISA level they
|
||||
were introduced in. */
|
||||
#define ISA_MIPS1 0x00000001
|
||||
#define ISA_MIPS2 0x00000002
|
||||
#define ISA_MIPS3 0x00000004
|
||||
#define ISA_MIPS4 0x00000008
|
||||
#define ISA_MIPS5 0x00000010
|
||||
#define ISA_MIPS32 0x00000020
|
||||
#define ISA_MIPS32R2 0x00000040
|
||||
#define ISA_MIPS64 0x00000080
|
||||
#define ISA_MIPS64R2 0x00000100
|
||||
|
||||
/* MIPS ASE */
|
||||
#define ASE_MIPS16 0x00001000
|
||||
#define ASE_MIPS3D 0x00002000
|
||||
#define ASE_MDMX 0x00004000
|
||||
#define ASE_DSP 0x00008000
|
||||
#define ASE_DSPR2 0x00010000
|
||||
|
||||
/* Chip specific instructions. */
|
||||
/* Currently void */
|
||||
|
||||
/* MIPS CPU defines. */
|
||||
#define CPU_MIPS1 (ISA_MIPS1)
|
||||
#define CPU_MIPS2 (CPU_MIPS1 | ISA_MIPS2)
|
||||
#define CPU_MIPS3 (CPU_MIPS2 | ISA_MIPS3)
|
||||
#define CPU_MIPS4 (CPU_MIPS3 | ISA_MIPS4)
|
||||
#define CPU_MIPS5 (CPU_MIPS4 | ISA_MIPS5)
|
||||
|
||||
#define CPU_MIPS32 (CPU_MIPS2 | ISA_MIPS32)
|
||||
#define CPU_MIPS64 (CPU_MIPS5 | CPU_MIPS32 | ISA_MIPS64)
|
||||
|
||||
#define CPU_MIPS32R2 (CPU_MIPS32 | ISA_MIPS32R2)
|
||||
#define CPU_MIPS64R2 (CPU_MIPS64 | CPU_MIPS32R2 | ISA_MIPS64R2)
|
||||
|
||||
/* Strictly follow the architecture standard:
|
||||
- Disallow "special" instruction handling for PMON/SPIM.
|
||||
Note that we still maintain Count/Compare to match the host clock. */
|
||||
|
@ -1847,10 +1847,9 @@ void op_mtc0_status (void)
|
||||
(val & (1 << CP0St_UM)))
|
||||
env->hflags |= MIPS_HFLAG_UM;
|
||||
#ifdef TARGET_MIPS64
|
||||
if (!(env->CP0_Config0 & (0x3 << CP0C0_AT)) ||
|
||||
((env->hflags & MIPS_HFLAG_UM) &&
|
||||
if ((env->hflags & MIPS_HFLAG_UM) &&
|
||||
!(val & (1 << CP0St_PX)) &&
|
||||
!(val & (1 << CP0St_UX))))
|
||||
!(val & (1 << CP0St_UX)))
|
||||
env->hflags &= ~MIPS_HFLAG_64;
|
||||
#endif
|
||||
if (val & (1 << CP0St_CU1))
|
||||
@ -1906,7 +1905,7 @@ void op_mtc0_cause (void)
|
||||
{
|
||||
uint32_t mask = 0x00C00300;
|
||||
|
||||
if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) == (1 << CP0C0_AR))
|
||||
if (env->insn_flags & ISA_MIPS32R2)
|
||||
mask |= 1 << CP0Ca_DC;
|
||||
|
||||
env->CP0_Cause = (env->CP0_Cause & ~mask) | (T0 & mask);
|
||||
@ -3014,10 +3013,9 @@ void op_eret (void)
|
||||
(env->CP0_Status & (1 << CP0St_UM)))
|
||||
env->hflags |= MIPS_HFLAG_UM;
|
||||
#ifdef TARGET_MIPS64
|
||||
if (!(env->CP0_Config0 & (0x3 << CP0C0_AT)) ||
|
||||
((env->hflags & MIPS_HFLAG_UM) &&
|
||||
if ((env->hflags & MIPS_HFLAG_UM) &&
|
||||
!(env->CP0_Status & (1 << CP0St_PX)) &&
|
||||
!(env->CP0_Status & (1 << CP0St_UX))))
|
||||
!(env->CP0_Status & (1 << CP0St_UX)))
|
||||
env->hflags &= ~MIPS_HFLAG_64;
|
||||
#endif
|
||||
if (loglevel & CPU_LOG_EXEC)
|
||||
@ -3038,10 +3036,9 @@ void op_deret (void)
|
||||
(env->CP0_Status & (1 << CP0St_UM)))
|
||||
env->hflags |= MIPS_HFLAG_UM;
|
||||
#ifdef TARGET_MIPS64
|
||||
if (!(env->CP0_Config0 & (0x3 << CP0C0_AT)) ||
|
||||
((env->hflags & MIPS_HFLAG_UM) &&
|
||||
if ((env->hflags & MIPS_HFLAG_UM) &&
|
||||
!(env->CP0_Status & (1 << CP0St_PX)) &&
|
||||
!(env->CP0_Status & (1 << CP0St_UX))))
|
||||
!(env->CP0_Status & (1 << CP0St_UX)))
|
||||
env->hflags &= ~MIPS_HFLAG_64;
|
||||
#endif
|
||||
if (loglevel & CPU_LOG_EXEC)
|
||||
|
@ -142,7 +142,7 @@ enum {
|
||||
OPC_SRL = 0x02 | OPC_SPECIAL, /* also ROTR */
|
||||
OPC_SRA = 0x03 | OPC_SPECIAL,
|
||||
OPC_SLLV = 0x04 | OPC_SPECIAL,
|
||||
OPC_SRLV = 0x06 | OPC_SPECIAL,
|
||||
OPC_SRLV = 0x06 | OPC_SPECIAL, /* also ROTRV */
|
||||
OPC_SRAV = 0x07 | OPC_SPECIAL,
|
||||
OPC_DSLLV = 0x14 | OPC_SPECIAL,
|
||||
OPC_DSRLV = 0x16 | OPC_SPECIAL, /* also DROTRV */
|
||||
@ -761,10 +761,10 @@ void check_cp1_registers(DisasContext *ctx, int regs)
|
||||
}
|
||||
|
||||
/* This code generates a "reserved instruction" exception if the
|
||||
CPU is not a MIPS R2 (or higher) CPU. */
|
||||
static inline void check_mips_r2(CPUState *env, DisasContext *ctx)
|
||||
CPU does not support the instruction set corresponding to flags. */
|
||||
static inline void check_insn(CPUState *env, DisasContext *ctx, int flags)
|
||||
{
|
||||
if ((env->CP0_Config0 & (0x7 << CP0C0_AR)) < (1 << CP0C0_AR))
|
||||
if (unlikely(!(env->insn_flags & flags)))
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
}
|
||||
|
||||
@ -776,6 +776,14 @@ static inline void check_mips_mt(CPUState *env, DisasContext *ctx)
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
}
|
||||
|
||||
/* This code generates a "reserved instruction" exception if 64-bit
|
||||
instructions are not enabled. */
|
||||
static inline void check_mips_64(DisasContext *ctx)
|
||||
{
|
||||
if (!(ctx->hflags & MIPS_HFLAG_64))
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
#define op_ldst(name) gen_op_##name##_raw()
|
||||
#define OP_LD_TABLE(width)
|
||||
@ -1024,8 +1032,8 @@ static void gen_flt_ldst (DisasContext *ctx, uint32_t opc, int ft,
|
||||
}
|
||||
|
||||
/* Arithmetic with immediate operand */
|
||||
static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,
|
||||
int rs, int16_t imm)
|
||||
static void gen_arith_imm (CPUState *env, DisasContext *ctx, uint32_t opc,
|
||||
int rt, int rs, int16_t imm)
|
||||
{
|
||||
target_ulong uimm;
|
||||
const char *opn = "imm arith";
|
||||
@ -1132,8 +1140,14 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,
|
||||
opn = "srl";
|
||||
break;
|
||||
case 1:
|
||||
gen_op_rotr();
|
||||
opn = "rotr";
|
||||
/* rotr is decoded as srl on non-R2 CPUs */
|
||||
if (env->insn_flags & ISA_MIPS32R2) {
|
||||
gen_op_rotr();
|
||||
opn = "rotr";
|
||||
} else {
|
||||
gen_op_srl();
|
||||
opn = "srl";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MIPS_INVAL("invalid srl flag");
|
||||
@ -1157,8 +1171,14 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,
|
||||
opn = "dsrl";
|
||||
break;
|
||||
case 1:
|
||||
gen_op_drotr();
|
||||
opn = "drotr";
|
||||
/* drotr is decoded as dsrl on non-R2 CPUs */
|
||||
if (env->insn_flags & ISA_MIPS32R2) {
|
||||
gen_op_drotr();
|
||||
opn = "drotr";
|
||||
} else {
|
||||
gen_op_dsrl();
|
||||
opn = "dsrl";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MIPS_INVAL("invalid dsrl flag");
|
||||
@ -1181,8 +1201,14 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,
|
||||
opn = "dsrl32";
|
||||
break;
|
||||
case 1:
|
||||
gen_op_drotr32();
|
||||
opn = "drotr32";
|
||||
/* drotr32 is decoded as dsrl32 on non-R2 CPUs */
|
||||
if (env->insn_flags & ISA_MIPS32R2) {
|
||||
gen_op_drotr32();
|
||||
opn = "drotr32";
|
||||
} else {
|
||||
gen_op_dsrl32();
|
||||
opn = "dsrl32";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MIPS_INVAL("invalid dsrl32 flag");
|
||||
@ -1201,7 +1227,7 @@ static void gen_arith_imm (DisasContext *ctx, uint32_t opc, int rt,
|
||||
}
|
||||
|
||||
/* Arithmetic */
|
||||
static void gen_arith (DisasContext *ctx, uint32_t opc,
|
||||
static void gen_arith (CPUState *env, DisasContext *ctx, uint32_t opc,
|
||||
int rd, int rs, int rt)
|
||||
{
|
||||
const char *opn = "arith";
|
||||
@ -1305,8 +1331,14 @@ static void gen_arith (DisasContext *ctx, uint32_t opc,
|
||||
opn = "srlv";
|
||||
break;
|
||||
case 1:
|
||||
gen_op_rotrv();
|
||||
opn = "rotrv";
|
||||
/* rotrv is decoded as srlv on non-R2 CPUs */
|
||||
if (env->insn_flags & ISA_MIPS32R2) {
|
||||
gen_op_rotrv();
|
||||
opn = "rotrv";
|
||||
} else {
|
||||
gen_op_srlv();
|
||||
opn = "srlv";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MIPS_INVAL("invalid srlv flag");
|
||||
@ -1330,8 +1362,14 @@ static void gen_arith (DisasContext *ctx, uint32_t opc,
|
||||
opn = "dsrlv";
|
||||
break;
|
||||
case 1:
|
||||
gen_op_drotrv();
|
||||
opn = "drotrv";
|
||||
/* drotrv is decoded as dsrlv on non-R2 CPUs */
|
||||
if (env->insn_flags & ISA_MIPS32R2) {
|
||||
gen_op_drotrv();
|
||||
opn = "drotrv";
|
||||
} else {
|
||||
gen_op_dsrlv();
|
||||
opn = "dsrlv";
|
||||
}
|
||||
break;
|
||||
default:
|
||||
MIPS_INVAL("invalid dsrlv flag");
|
||||
@ -1910,6 +1948,9 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
{
|
||||
const char *rn = "invalid";
|
||||
|
||||
if (sel != 0)
|
||||
check_insn(env, ctx, ISA_MIPS32);
|
||||
|
||||
switch (reg) {
|
||||
case 0:
|
||||
switch (sel) {
|
||||
@ -2057,7 +2098,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
rn = "PageMask";
|
||||
break;
|
||||
case 1:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mfc0_pagegrain();
|
||||
rn = "PageGrain";
|
||||
break;
|
||||
@ -2072,22 +2113,27 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
rn = "Wired";
|
||||
break;
|
||||
case 1:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mfc0_srsconf0();
|
||||
rn = "SRSConf0";
|
||||
break;
|
||||
case 2:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mfc0_srsconf1();
|
||||
rn = "SRSConf1";
|
||||
break;
|
||||
case 3:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mfc0_srsconf2();
|
||||
rn = "SRSConf2";
|
||||
break;
|
||||
case 4:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mfc0_srsconf3();
|
||||
rn = "SRSConf3";
|
||||
break;
|
||||
case 5:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mfc0_srsconf4();
|
||||
rn = "SRSConf4";
|
||||
break;
|
||||
@ -2098,7 +2144,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
case 7:
|
||||
switch (sel) {
|
||||
case 0:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mfc0_hwrena();
|
||||
rn = "HWREna";
|
||||
break;
|
||||
@ -2155,17 +2201,17 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
rn = "Status";
|
||||
break;
|
||||
case 1:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mfc0_intctl();
|
||||
rn = "IntCtl";
|
||||
break;
|
||||
case 2:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mfc0_srsctl();
|
||||
rn = "SRSCtl";
|
||||
break;
|
||||
case 3:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mfc0_srsmap();
|
||||
rn = "SRSMap";
|
||||
break;
|
||||
@ -2200,7 +2246,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
rn = "PRid";
|
||||
break;
|
||||
case 1:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mfc0_ebase();
|
||||
rn = "EBase";
|
||||
break;
|
||||
@ -2274,8 +2320,7 @@ static void gen_mfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
switch (sel) {
|
||||
case 0:
|
||||
#ifdef TARGET_MIPS64
|
||||
if (!(ctx->hflags & MIPS_HFLAG_64))
|
||||
goto die;
|
||||
check_insn(env, ctx, ISA_MIPS3);
|
||||
gen_op_mfc0_xcontext();
|
||||
rn = "XContext";
|
||||
break;
|
||||
@ -2471,6 +2516,9 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
{
|
||||
const char *rn = "invalid";
|
||||
|
||||
if (sel != 0)
|
||||
check_insn(env, ctx, ISA_MIPS32);
|
||||
|
||||
switch (reg) {
|
||||
case 0:
|
||||
switch (sel) {
|
||||
@ -2618,7 +2666,7 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
rn = "PageMask";
|
||||
break;
|
||||
case 1:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mtc0_pagegrain();
|
||||
rn = "PageGrain";
|
||||
break;
|
||||
@ -2633,22 +2681,27 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
rn = "Wired";
|
||||
break;
|
||||
case 1:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mtc0_srsconf0();
|
||||
rn = "SRSConf0";
|
||||
break;
|
||||
case 2:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mtc0_srsconf1();
|
||||
rn = "SRSConf1";
|
||||
break;
|
||||
case 3:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mtc0_srsconf2();
|
||||
rn = "SRSConf2";
|
||||
break;
|
||||
case 4:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mtc0_srsconf3();
|
||||
rn = "SRSConf3";
|
||||
break;
|
||||
case 5:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mtc0_srsconf4();
|
||||
rn = "SRSConf4";
|
||||
break;
|
||||
@ -2659,7 +2712,7 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
case 7:
|
||||
switch (sel) {
|
||||
case 0:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mtc0_hwrena();
|
||||
rn = "HWREna";
|
||||
break;
|
||||
@ -2717,21 +2770,21 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
rn = "Status";
|
||||
break;
|
||||
case 1:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mtc0_intctl();
|
||||
/* Stop translation as we may have switched the execution mode */
|
||||
ctx->bstate = BS_STOP;
|
||||
rn = "IntCtl";
|
||||
break;
|
||||
case 2:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mtc0_srsctl();
|
||||
/* Stop translation as we may have switched the execution mode */
|
||||
ctx->bstate = BS_STOP;
|
||||
rn = "SRSCtl";
|
||||
break;
|
||||
case 3:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mtc0_srsmap();
|
||||
/* Stop translation as we may have switched the execution mode */
|
||||
ctx->bstate = BS_STOP;
|
||||
@ -2770,7 +2823,7 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
rn = "PRid";
|
||||
break;
|
||||
case 1:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mtc0_ebase();
|
||||
rn = "EBase";
|
||||
break;
|
||||
@ -2849,8 +2902,7 @@ static void gen_mtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
switch (sel) {
|
||||
case 0:
|
||||
#ifdef TARGET_MIPS64
|
||||
if (!(ctx->hflags & MIPS_HFLAG_64))
|
||||
goto die;
|
||||
check_insn(env, ctx, ISA_MIPS3);
|
||||
gen_op_mtc0_xcontext();
|
||||
rn = "XContext";
|
||||
break;
|
||||
@ -3064,6 +3116,9 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
{
|
||||
const char *rn = "invalid";
|
||||
|
||||
if (sel != 0)
|
||||
check_insn(env, ctx, ISA_MIPS64);
|
||||
|
||||
switch (reg) {
|
||||
case 0:
|
||||
switch (sel) {
|
||||
@ -3211,7 +3266,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
rn = "PageMask";
|
||||
break;
|
||||
case 1:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mfc0_pagegrain();
|
||||
rn = "PageGrain";
|
||||
break;
|
||||
@ -3226,22 +3281,27 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
rn = "Wired";
|
||||
break;
|
||||
case 1:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mfc0_srsconf0();
|
||||
rn = "SRSConf0";
|
||||
break;
|
||||
case 2:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mfc0_srsconf1();
|
||||
rn = "SRSConf1";
|
||||
break;
|
||||
case 3:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mfc0_srsconf2();
|
||||
rn = "SRSConf2";
|
||||
break;
|
||||
case 4:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mfc0_srsconf3();
|
||||
rn = "SRSConf3";
|
||||
break;
|
||||
case 5:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mfc0_srsconf4();
|
||||
rn = "SRSConf4";
|
||||
break;
|
||||
@ -3252,7 +3312,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
case 7:
|
||||
switch (sel) {
|
||||
case 0:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mfc0_hwrena();
|
||||
rn = "HWREna";
|
||||
break;
|
||||
@ -3309,17 +3369,17 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
rn = "Status";
|
||||
break;
|
||||
case 1:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mfc0_intctl();
|
||||
rn = "IntCtl";
|
||||
break;
|
||||
case 2:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mfc0_srsctl();
|
||||
rn = "SRSCtl";
|
||||
break;
|
||||
case 3:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mfc0_srsmap();
|
||||
rn = "SRSMap";
|
||||
break;
|
||||
@ -3354,7 +3414,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
rn = "PRid";
|
||||
break;
|
||||
case 1:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mfc0_ebase();
|
||||
rn = "EBase";
|
||||
break;
|
||||
@ -3418,6 +3478,7 @@ static void gen_dmfc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
case 20:
|
||||
switch (sel) {
|
||||
case 0:
|
||||
check_insn(env, ctx, ISA_MIPS3);
|
||||
gen_op_dmfc0_xcontext();
|
||||
rn = "XContext";
|
||||
break;
|
||||
@ -3612,6 +3673,9 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
{
|
||||
const char *rn = "invalid";
|
||||
|
||||
if (sel != 0)
|
||||
check_insn(env, ctx, ISA_MIPS64);
|
||||
|
||||
switch (reg) {
|
||||
case 0:
|
||||
switch (sel) {
|
||||
@ -3759,7 +3823,7 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
rn = "PageMask";
|
||||
break;
|
||||
case 1:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mtc0_pagegrain();
|
||||
rn = "PageGrain";
|
||||
break;
|
||||
@ -3774,22 +3838,27 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
rn = "Wired";
|
||||
break;
|
||||
case 1:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mtc0_srsconf0();
|
||||
rn = "SRSConf0";
|
||||
break;
|
||||
case 2:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mtc0_srsconf1();
|
||||
rn = "SRSConf1";
|
||||
break;
|
||||
case 3:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mtc0_srsconf2();
|
||||
rn = "SRSConf2";
|
||||
break;
|
||||
case 4:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mtc0_srsconf3();
|
||||
rn = "SRSConf3";
|
||||
break;
|
||||
case 5:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mtc0_srsconf4();
|
||||
rn = "SRSConf4";
|
||||
break;
|
||||
@ -3800,7 +3869,7 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
case 7:
|
||||
switch (sel) {
|
||||
case 0:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mtc0_hwrena();
|
||||
rn = "HWREna";
|
||||
break;
|
||||
@ -3858,21 +3927,21 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
rn = "Status";
|
||||
break;
|
||||
case 1:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mtc0_intctl();
|
||||
/* Stop translation as we may have switched the execution mode */
|
||||
ctx->bstate = BS_STOP;
|
||||
rn = "IntCtl";
|
||||
break;
|
||||
case 2:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mtc0_srsctl();
|
||||
/* Stop translation as we may have switched the execution mode */
|
||||
ctx->bstate = BS_STOP;
|
||||
rn = "SRSCtl";
|
||||
break;
|
||||
case 3:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mtc0_srsmap();
|
||||
/* Stop translation as we may have switched the execution mode */
|
||||
ctx->bstate = BS_STOP;
|
||||
@ -3911,7 +3980,7 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
rn = "PRid";
|
||||
break;
|
||||
case 1:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_mtc0_ebase();
|
||||
rn = "EBase";
|
||||
break;
|
||||
@ -3980,6 +4049,7 @@ static void gen_dmtc0 (CPUState *env, DisasContext *ctx, int reg, int sel)
|
||||
case 20:
|
||||
switch (sel) {
|
||||
case 0:
|
||||
check_insn(env, ctx, ISA_MIPS3);
|
||||
gen_op_mtc0_xcontext();
|
||||
rn = "XContext";
|
||||
break;
|
||||
@ -4535,8 +4605,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
|
||||
break;
|
||||
#ifdef TARGET_MIPS64
|
||||
case OPC_DMFC0:
|
||||
if (!(ctx->hflags & MIPS_HFLAG_64))
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
check_insn(env, ctx, ISA_MIPS3);
|
||||
if (rt == 0) {
|
||||
/* Treat as NOP. */
|
||||
return;
|
||||
@ -4546,8 +4615,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
|
||||
opn = "dmfc0";
|
||||
break;
|
||||
case OPC_DMTC0:
|
||||
if (!(ctx->hflags & MIPS_HFLAG_64))
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
check_insn(env, ctx, ISA_MIPS3);
|
||||
GEN_LOAD_REG_TN(T0, rt);
|
||||
gen_dmtc0(env, ctx, rd, ctx->opcode & 0x7);
|
||||
opn = "dmtc0";
|
||||
@ -4597,11 +4665,13 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
|
||||
break;
|
||||
case OPC_ERET:
|
||||
opn = "eret";
|
||||
check_insn(env, ctx, ISA_MIPS2);
|
||||
gen_op_eret();
|
||||
ctx->bstate = BS_EXCP;
|
||||
break;
|
||||
case OPC_DERET:
|
||||
opn = "deret";
|
||||
check_insn(env, ctx, ISA_MIPS32);
|
||||
if (!(ctx->hflags & MIPS_HFLAG_DM)) {
|
||||
MIPS_INVAL(opn);
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
@ -4612,6 +4682,7 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
|
||||
break;
|
||||
case OPC_WAIT:
|
||||
opn = "wait";
|
||||
check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
|
||||
/* If we get an exception, we want to restart at next instruction */
|
||||
ctx->pc += 4;
|
||||
save_cpu_state(ctx, 1);
|
||||
@ -4629,12 +4700,15 @@ static void gen_cp0 (CPUState *env, DisasContext *ctx, uint32_t opc, int rt, int
|
||||
}
|
||||
|
||||
/* CP1 Branches (before delay slot) */
|
||||
static void gen_compute_branch1 (DisasContext *ctx, uint32_t op,
|
||||
static void gen_compute_branch1 (CPUState *env, DisasContext *ctx, uint32_t op,
|
||||
int32_t cc, int32_t offset)
|
||||
{
|
||||
target_ulong btarget;
|
||||
const char *opn = "cp1 cond branch";
|
||||
|
||||
if (cc != 0)
|
||||
check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
|
||||
|
||||
btarget = ctx->pc + 4 + offset;
|
||||
|
||||
switch (op) {
|
||||
@ -5843,14 +5917,15 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||
switch (op1) {
|
||||
case OPC_SLL: /* Arithmetic with immediate */
|
||||
case OPC_SRL ... OPC_SRA:
|
||||
gen_arith_imm(ctx, op1, rd, rt, sa);
|
||||
gen_arith_imm(env, ctx, op1, rd, rt, sa);
|
||||
break;
|
||||
case OPC_MOVZ ... OPC_MOVN:
|
||||
check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
|
||||
case OPC_SLLV: /* Arithmetic */
|
||||
case OPC_SRLV ... OPC_SRAV:
|
||||
case OPC_MOVZ ... OPC_MOVN:
|
||||
case OPC_ADD ... OPC_NOR:
|
||||
case OPC_SLT ... OPC_SLTU:
|
||||
gen_arith(ctx, op1, rd, rs, rt);
|
||||
gen_arith(env, ctx, op1, rd, rs, rt);
|
||||
break;
|
||||
case OPC_MULT ... OPC_DIVU:
|
||||
gen_muldiv(ctx, op1, rs, rt);
|
||||
@ -5899,6 +5974,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||
break;
|
||||
|
||||
case OPC_MOVCI:
|
||||
check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
|
||||
if (env->CP0_Config1 & (1 << CP0C1_FP)) {
|
||||
save_cpu_state(ctx, 1);
|
||||
check_cp1_enabled(ctx);
|
||||
@ -5915,20 +5991,20 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||
case OPC_DSRL ... OPC_DSRA:
|
||||
case OPC_DSLL32:
|
||||
case OPC_DSRL32 ... OPC_DSRA32:
|
||||
if (!(ctx->hflags & MIPS_HFLAG_64))
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
gen_arith_imm(ctx, op1, rd, rt, sa);
|
||||
check_insn(env, ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_arith_imm(env, ctx, op1, rd, rt, sa);
|
||||
break;
|
||||
case OPC_DSLLV:
|
||||
case OPC_DSRLV ... OPC_DSRAV:
|
||||
case OPC_DADD ... OPC_DSUBU:
|
||||
if (!(ctx->hflags & MIPS_HFLAG_64))
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
gen_arith(ctx, op1, rd, rs, rt);
|
||||
check_insn(env, ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_arith(env, ctx, op1, rd, rs, rt);
|
||||
break;
|
||||
case OPC_DMULT ... OPC_DDIVU:
|
||||
if (!(ctx->hflags & MIPS_HFLAG_64))
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
check_insn(env, ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_muldiv(ctx, op1, rs, rt);
|
||||
break;
|
||||
#endif
|
||||
@ -5943,18 +6019,21 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||
switch (op1) {
|
||||
case OPC_MADD ... OPC_MADDU: /* Multiply and add/sub */
|
||||
case OPC_MSUB ... OPC_MSUBU:
|
||||
check_insn(env, ctx, ISA_MIPS32);
|
||||
gen_muldiv(ctx, op1, rs, rt);
|
||||
break;
|
||||
case OPC_MUL:
|
||||
gen_arith(ctx, op1, rd, rs, rt);
|
||||
gen_arith(env, ctx, op1, rd, rs, rt);
|
||||
break;
|
||||
case OPC_CLZ ... OPC_CLO:
|
||||
check_insn(env, ctx, ISA_MIPS32);
|
||||
gen_cl(ctx, op1, rd, rs);
|
||||
break;
|
||||
case OPC_SDBBP:
|
||||
/* XXX: not clear which exception should be raised
|
||||
* when in debug mode...
|
||||
*/
|
||||
check_insn(env, ctx, ISA_MIPS32);
|
||||
if (!(ctx->hflags & MIPS_HFLAG_DM)) {
|
||||
generate_exception(ctx, EXCP_DBp);
|
||||
} else {
|
||||
@ -5964,8 +6043,8 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||
break;
|
||||
#ifdef TARGET_MIPS64
|
||||
case OPC_DCLZ ... OPC_DCLO:
|
||||
if (!(ctx->hflags & MIPS_HFLAG_64))
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
check_insn(env, ctx, ISA_MIPS64);
|
||||
check_mips_64(ctx);
|
||||
gen_cl(ctx, op1, rd, rs);
|
||||
break;
|
||||
#endif
|
||||
@ -5976,14 +6055,15 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||
}
|
||||
break;
|
||||
case OPC_SPECIAL3:
|
||||
check_mips_r2(env, ctx);
|
||||
op1 = MASK_SPECIAL3(ctx->opcode);
|
||||
switch (op1) {
|
||||
case OPC_EXT:
|
||||
case OPC_INS:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_bitops(ctx, op1, rt, rs, sa, rd);
|
||||
break;
|
||||
case OPC_BSHFL:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
op2 = MASK_BSHFL(ctx->opcode);
|
||||
switch (op2) {
|
||||
case OPC_WSBH:
|
||||
@ -6006,6 +6086,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||
GEN_STORE_TN_REG(rd, T0);
|
||||
break;
|
||||
case OPC_RDHWR:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
switch (rd) {
|
||||
case 0:
|
||||
save_cpu_state(ctx, 1);
|
||||
@ -6050,13 +6131,13 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||
#ifdef TARGET_MIPS64
|
||||
case OPC_DEXTM ... OPC_DEXT:
|
||||
case OPC_DINSM ... OPC_DINS:
|
||||
if (!(ctx->hflags & MIPS_HFLAG_64))
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
check_insn(env, ctx, ISA_MIPS64R2);
|
||||
check_mips_64(ctx);
|
||||
gen_bitops(ctx, op1, rt, rs, sa, rd);
|
||||
break;
|
||||
case OPC_DBSHFL:
|
||||
if (!(ctx->hflags & MIPS_HFLAG_64))
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
check_insn(env, ctx, ISA_MIPS64R2);
|
||||
check_mips_64(ctx);
|
||||
op2 = MASK_DBSHFL(ctx->opcode);
|
||||
switch (op2) {
|
||||
case OPC_DSBH:
|
||||
@ -6092,7 +6173,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||
gen_trap(ctx, op1, rs, -1, imm);
|
||||
break;
|
||||
case OPC_SYNCI:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
/* Treat as NOP. */
|
||||
break;
|
||||
default: /* Invalid */
|
||||
@ -6120,7 +6201,6 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||
gen_cp0(env, ctx, MASK_C0(ctx->opcode), rt, rd);
|
||||
break;
|
||||
case OPC_MFMC0:
|
||||
check_mips_r2(env, ctx);
|
||||
op2 = MASK_MFMC0(ctx->opcode);
|
||||
switch (op2) {
|
||||
case OPC_DMT:
|
||||
@ -6140,11 +6220,13 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||
gen_op_evpe();
|
||||
break;
|
||||
case OPC_DI:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_di();
|
||||
/* Stop translation as we may have switched the execution mode */
|
||||
ctx->bstate = BS_STOP;
|
||||
break;
|
||||
case OPC_EI:
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
gen_op_ei();
|
||||
/* Stop translation as we may have switched the execution mode */
|
||||
ctx->bstate = BS_STOP;
|
||||
@ -6157,12 +6239,12 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||
GEN_STORE_TN_REG(rt, T0);
|
||||
break;
|
||||
case OPC_RDPGPR:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
GEN_LOAD_SRSREG_TN(T0, rt);
|
||||
GEN_STORE_TN_REG(rd, T0);
|
||||
break;
|
||||
case OPC_WRPGPR:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
GEN_LOAD_REG_TN(T0, rt);
|
||||
GEN_STORE_TN_SRSREG(rd, T0);
|
||||
break;
|
||||
@ -6173,7 +6255,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||
}
|
||||
break;
|
||||
case OPC_ADDI ... OPC_LUI: /* Arithmetic with immediate opcode */
|
||||
gen_arith_imm(ctx, op, rt, rs, imm);
|
||||
gen_arith_imm(env, ctx, op, rt, rs, imm);
|
||||
break;
|
||||
case OPC_J ... OPC_JAL: /* Jump */
|
||||
offset = (int32_t)(ctx->opcode & 0x3FFFFFF) << 2;
|
||||
@ -6191,9 +6273,11 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||
gen_ldst(ctx, op, rt, rs, imm);
|
||||
break;
|
||||
case OPC_CACHE:
|
||||
check_insn(env, ctx, ISA_MIPS3 | ISA_MIPS32);
|
||||
/* Treat as NOP. */
|
||||
break;
|
||||
case OPC_PREF:
|
||||
check_insn(env, ctx, ISA_MIPS4 | ISA_MIPS32);
|
||||
/* Treat as NOP. */
|
||||
break;
|
||||
|
||||
@ -6219,21 +6303,24 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||
switch (op1) {
|
||||
case OPC_MFHC1:
|
||||
case OPC_MTHC1:
|
||||
check_mips_r2(env, ctx);
|
||||
check_insn(env, ctx, ISA_MIPS32R2);
|
||||
case OPC_MFC1:
|
||||
case OPC_CFC1:
|
||||
case OPC_MTC1:
|
||||
case OPC_CTC1:
|
||||
gen_cp1(ctx, op1, rt, rd);
|
||||
break;
|
||||
#ifdef TARGET_MIPS64
|
||||
case OPC_DMFC1:
|
||||
case OPC_DMTC1:
|
||||
#endif
|
||||
check_insn(env, ctx, ISA_MIPS3);
|
||||
gen_cp1(ctx, op1, rt, rd);
|
||||
break;
|
||||
#endif
|
||||
case OPC_BC1:
|
||||
case OPC_BC1ANY2:
|
||||
case OPC_BC1ANY4:
|
||||
gen_compute_branch1(ctx, MASK_BC1(ctx->opcode),
|
||||
gen_compute_branch1(env, ctx, MASK_BC1(ctx->opcode),
|
||||
(rt >> 2) & 0x7, imm << 2);
|
||||
return;
|
||||
case OPC_S_FMT:
|
||||
@ -6315,24 +6402,22 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||
case OPC_LD:
|
||||
case OPC_SCD:
|
||||
case OPC_SD:
|
||||
if (!(ctx->hflags & MIPS_HFLAG_64))
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
check_insn(env, ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_ldst(ctx, op, rt, rs, imm);
|
||||
break;
|
||||
case OPC_DADDI ... OPC_DADDIU:
|
||||
if (!(ctx->hflags & MIPS_HFLAG_64))
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
gen_arith_imm(ctx, op, rt, rs, imm);
|
||||
check_insn(env, ctx, ISA_MIPS3);
|
||||
check_mips_64(ctx);
|
||||
gen_arith_imm(env, ctx, op, rt, rs, imm);
|
||||
break;
|
||||
#endif
|
||||
#ifdef MIPS_HAS_MIPS16
|
||||
case OPC_JALX:
|
||||
check_insn(env, ctx, ASE_MIPS16);
|
||||
/* MIPS16: Not implemented. */
|
||||
#endif
|
||||
#ifdef MIPS_HAS_MDMX
|
||||
case OPC_MDMX:
|
||||
check_insn(env, ctx, ASE_MDMX);
|
||||
/* MDMX: Not implemented. */
|
||||
#endif
|
||||
default: /* Invalid */
|
||||
MIPS_INVAL("major opcode");
|
||||
generate_exception(ctx, EXCP_RI);
|
||||
|
@ -80,6 +80,7 @@ struct mips_def_t {
|
||||
int32_t CP0_SRSConf3;
|
||||
int32_t CP0_SRSConf4_rw_bitmask;
|
||||
int32_t CP0_SRSConf4;
|
||||
int insn_flags;
|
||||
};
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -98,6 +99,7 @@ static mips_def_t mips_defs[] =
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x1278FF17,
|
||||
.insn_flags = CPU_MIPS32 | ASE_MIPS16,
|
||||
},
|
||||
{
|
||||
.name = "4KEcR1",
|
||||
@ -111,6 +113,7 @@ static mips_def_t mips_defs[] =
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x1278FF17,
|
||||
.insn_flags = CPU_MIPS32 | ASE_MIPS16,
|
||||
},
|
||||
{
|
||||
.name = "4KEc",
|
||||
@ -124,6 +127,7 @@ static mips_def_t mips_defs[] =
|
||||
.SYNCI_Step = 32,
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x1278FF17,
|
||||
.insn_flags = CPU_MIPS32R2 | ASE_MIPS16,
|
||||
},
|
||||
{
|
||||
.name = "24Kc",
|
||||
@ -138,6 +142,7 @@ static mips_def_t mips_defs[] =
|
||||
.CCRes = 2,
|
||||
/* No DSP implemented. */
|
||||
.CP0_Status_rw_bitmask = 0x1278FF17,
|
||||
.insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP,
|
||||
},
|
||||
{
|
||||
.name = "24Kf",
|
||||
@ -154,6 +159,7 @@ static mips_def_t mips_defs[] =
|
||||
.CP0_Status_rw_bitmask = 0x3678FF17,
|
||||
.CP1_fcr0 = (1 << FCR0_F64) | (1 << FCR0_L) | (1 << FCR0_W) |
|
||||
(1 << FCR0_D) | (1 << FCR0_S) | (0x93 << FCR0_PRID),
|
||||
.insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP,
|
||||
},
|
||||
{
|
||||
.name = "34Kf",
|
||||
@ -193,6 +199,7 @@ static mips_def_t mips_defs[] =
|
||||
.CP0_SRSConf4_rw_bitmask = 0x3fffffff,
|
||||
.CP0_SRSConf4 = (0x3fe << CP0SRSC4_SRS15) |
|
||||
(0x3fe << CP0SRSC4_SRS14) | (0x3fe << CP0SRSC4_SRS13),
|
||||
.insn_flags = CPU_MIPS32R2 | ASE_MIPS16 | ASE_DSP,
|
||||
},
|
||||
#ifdef TARGET_MIPS64
|
||||
{
|
||||
@ -210,6 +217,7 @@ static mips_def_t mips_defs[] =
|
||||
/* The R4000 has a full 64bit FPU doesn't use the fcr0 bits. */
|
||||
.CP1_fcr0 = (0x5 << FCR0_PRID) | (0x0 << FCR0_REV),
|
||||
.SEGBITS = 40,
|
||||
.insn_flags = CPU_MIPS3,
|
||||
},
|
||||
{
|
||||
.name = "5Kc",
|
||||
@ -225,6 +233,7 @@ static mips_def_t mips_defs[] =
|
||||
.CCRes = 2,
|
||||
.CP0_Status_rw_bitmask = 0x32F8FFFF,
|
||||
.SEGBITS = 42,
|
||||
.insn_flags = CPU_MIPS64,
|
||||
},
|
||||
{
|
||||
.name = "5Kf",
|
||||
@ -243,6 +252,7 @@ static mips_def_t mips_defs[] =
|
||||
.CP1_fcr0 = (1 << FCR0_D) | (1 << FCR0_S) |
|
||||
(0x81 << FCR0_PRID) | (0x0 << FCR0_REV),
|
||||
.SEGBITS = 42,
|
||||
.insn_flags = CPU_MIPS64,
|
||||
},
|
||||
{
|
||||
.name = "20Kc",
|
||||
@ -264,6 +274,7 @@ static mips_def_t mips_defs[] =
|
||||
(1 << FCR0_D) | (1 << FCR0_S) |
|
||||
(0x82 << FCR0_PRID) | (0x0 << FCR0_REV),
|
||||
.SEGBITS = 40,
|
||||
.insn_flags = CPU_MIPS64 | ASE_MIPS3D,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
@ -406,7 +417,7 @@ int cpu_mips_register (CPUMIPSState *env, mips_def_t *def)
|
||||
env->CP0_TCStatus_rw_bitmask = def->CP0_TCStatus_rw_bitmask;
|
||||
env->CP0_SRSCtl = def->CP0_SRSCtl;
|
||||
#ifdef TARGET_MIPS64
|
||||
if ((env->CP0_Config0 & (0x3 << CP0C0_AT)))
|
||||
if (def->insn_flags & ISA_MIPS3)
|
||||
{
|
||||
env->hflags |= MIPS_HFLAG_64;
|
||||
env->SEGBITS = def->SEGBITS;
|
||||
@ -426,6 +437,7 @@ int cpu_mips_register (CPUMIPSState *env, mips_def_t *def)
|
||||
env->CP0_SRSConf3 = def->CP0_SRSConf3;
|
||||
env->CP0_SRSConf4_rw_bitmask = def->CP0_SRSConf4_rw_bitmask;
|
||||
env->CP0_SRSConf4 = def->CP0_SRSConf4;
|
||||
env->insn_flags = def->insn_flags;
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
mmu_init(env, def);
|
||||
|
Loading…
Reference in New Issue
Block a user