mirror of https://github.com/xemu-project/xemu.git
MIPS COP1X (and related) instructions, by Richard Sandiford.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3877 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
6341fdcb78
commit
b8aa4598e2
|
@ -417,7 +417,7 @@ struct CPUMIPSState {
|
||||||
int user_mode_only; /* user mode only simulation */
|
int user_mode_only; /* user mode only simulation */
|
||||||
uint32_t hflags; /* CPU State */
|
uint32_t hflags; /* CPU State */
|
||||||
/* TMASK defines different execution modes */
|
/* TMASK defines different execution modes */
|
||||||
#define MIPS_HFLAG_TMASK 0x00FF
|
#define MIPS_HFLAG_TMASK 0x01FF
|
||||||
#define MIPS_HFLAG_MODE 0x0007 /* execution modes */
|
#define MIPS_HFLAG_MODE 0x0007 /* execution modes */
|
||||||
/* The KSU flags must be the lowest bits in hflags. The flag order
|
/* The KSU flags must be the lowest bits in hflags. The flag order
|
||||||
must be the same as defined for CP0 Status. This allows to use
|
must be the same as defined for CP0 Status. This allows to use
|
||||||
|
@ -431,16 +431,20 @@ struct CPUMIPSState {
|
||||||
#define MIPS_HFLAG_CP0 0x0010 /* CP0 enabled */
|
#define MIPS_HFLAG_CP0 0x0010 /* CP0 enabled */
|
||||||
#define MIPS_HFLAG_FPU 0x0020 /* FPU enabled */
|
#define MIPS_HFLAG_FPU 0x0020 /* FPU enabled */
|
||||||
#define MIPS_HFLAG_F64 0x0040 /* 64-bit FPU enabled */
|
#define MIPS_HFLAG_F64 0x0040 /* 64-bit FPU enabled */
|
||||||
#define MIPS_HFLAG_RE 0x0080 /* Reversed endianness */
|
/* True if the MIPS IV COP1X instructions can be used. This also
|
||||||
|
controls the non-COP1X instructions RECIP.S, RECIP.D, RSQRT.S
|
||||||
|
and RSQRT.D. */
|
||||||
|
#define MIPS_HFLAG_COP1X 0x0080 /* COP1X instructions enabled */
|
||||||
|
#define MIPS_HFLAG_RE 0x0100 /* Reversed endianness */
|
||||||
/* If translation is interrupted between the branch instruction and
|
/* If translation is interrupted between the branch instruction and
|
||||||
* the delay slot, record what type of branch it is so that we can
|
* the delay slot, record what type of branch it is so that we can
|
||||||
* resume translation properly. It might be possible to reduce
|
* resume translation properly. It might be possible to reduce
|
||||||
* this from three bits to two. */
|
* this from three bits to two. */
|
||||||
#define MIPS_HFLAG_BMASK 0x0700
|
#define MIPS_HFLAG_BMASK 0x0e00
|
||||||
#define MIPS_HFLAG_B 0x0100 /* Unconditional branch */
|
#define MIPS_HFLAG_B 0x0200 /* Unconditional branch */
|
||||||
#define MIPS_HFLAG_BC 0x0200 /* Conditional branch */
|
#define MIPS_HFLAG_BC 0x0400 /* Conditional branch */
|
||||||
#define MIPS_HFLAG_BL 0x0300 /* Likely branch */
|
#define MIPS_HFLAG_BL 0x0600 /* Likely branch */
|
||||||
#define MIPS_HFLAG_BR 0x0400 /* branch to register (can't link TB) */
|
#define MIPS_HFLAG_BR 0x0800 /* branch to register (can't link TB) */
|
||||||
target_ulong btarget; /* Jump / branch target */
|
target_ulong btarget; /* Jump / branch target */
|
||||||
int bcond; /* Branch condition (if needed) */
|
int bcond; /* Branch condition (if needed) */
|
||||||
|
|
||||||
|
|
|
@ -237,8 +237,8 @@ static always_inline int cpu_halted(CPUState *env)
|
||||||
|
|
||||||
static always_inline void compute_hflags(CPUState *env)
|
static always_inline void compute_hflags(CPUState *env)
|
||||||
{
|
{
|
||||||
env->hflags &= ~(MIPS_HFLAG_64 | MIPS_HFLAG_CP0 | MIPS_HFLAG_F64 |
|
env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
|
||||||
MIPS_HFLAG_FPU | MIPS_HFLAG_KSU);
|
MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU);
|
||||||
if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
|
if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
|
||||||
!(env->CP0_Status & (1 << CP0St_ERL)) &&
|
!(env->CP0_Status & (1 << CP0St_ERL)) &&
|
||||||
!(env->hflags & MIPS_HFLAG_DM)) {
|
!(env->hflags & MIPS_HFLAG_DM)) {
|
||||||
|
@ -257,6 +257,20 @@ static always_inline void compute_hflags(CPUState *env)
|
||||||
env->hflags |= MIPS_HFLAG_FPU;
|
env->hflags |= MIPS_HFLAG_FPU;
|
||||||
if (env->CP0_Status & (1 << CP0St_FR))
|
if (env->CP0_Status & (1 << CP0St_FR))
|
||||||
env->hflags |= MIPS_HFLAG_F64;
|
env->hflags |= MIPS_HFLAG_F64;
|
||||||
|
if (env->insn_flags & ISA_MIPS32R2) {
|
||||||
|
if (env->fpu->fcr0 & FCR0_F64)
|
||||||
|
env->hflags |= MIPS_HFLAG_COP1X;
|
||||||
|
} else if (env->insn_flags & ISA_MIPS32) {
|
||||||
|
if (env->hflags & MIPS_HFLAG_64)
|
||||||
|
env->hflags |= MIPS_HFLAG_COP1X;
|
||||||
|
} else if (env->insn_flags & ISA_MIPS4) {
|
||||||
|
/* All supported MIPS IV CPUs use the XX (CU3) to enable
|
||||||
|
and disable the MIPS IV extensions to the MIPS III ISA.
|
||||||
|
Some other MIPS IV CPUs ignore the bit, so the check here
|
||||||
|
would be too restrictive for them. */
|
||||||
|
if (env->CP0_Status & (1 << CP0St_CU3))
|
||||||
|
env->hflags |= MIPS_HFLAG_COP1X;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !defined(__QEMU_MIPS_EXEC_H__) */
|
#endif /* !defined(__QEMU_MIPS_EXEC_H__) */
|
||||||
|
|
|
@ -794,9 +794,22 @@ static always_inline void check_cp1_enabled(DisasContext *ctx)
|
||||||
generate_exception_err(ctx, EXCP_CpU, 1);
|
generate_exception_err(ctx, EXCP_CpU, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Verify that the processor is running with COP1X instructions enabled.
|
||||||
|
This is associated with the nabla symbol in the MIPS32 and MIPS64
|
||||||
|
opcode tables. */
|
||||||
|
|
||||||
|
static always_inline void check_cop1x(DisasContext *ctx)
|
||||||
|
{
|
||||||
|
if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
|
||||||
|
generate_exception(ctx, EXCP_RI);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Verify that the processor is running with 64-bit floating-point
|
||||||
|
operations enabled. */
|
||||||
|
|
||||||
static always_inline void check_cp1_64bitmode(DisasContext *ctx)
|
static always_inline void check_cp1_64bitmode(DisasContext *ctx)
|
||||||
{
|
{
|
||||||
if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64)))
|
if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
|
||||||
generate_exception(ctx, EXCP_RI);
|
generate_exception(ctx, EXCP_RI);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5178,12 +5191,14 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
|
||||||
opn = "movn.s";
|
opn = "movn.s";
|
||||||
break;
|
break;
|
||||||
case FOP(21, 16):
|
case FOP(21, 16):
|
||||||
|
check_cop1x(ctx);
|
||||||
GEN_LOAD_FREG_FTN(WT0, fs);
|
GEN_LOAD_FREG_FTN(WT0, fs);
|
||||||
gen_op_float_recip_s();
|
gen_op_float_recip_s();
|
||||||
GEN_STORE_FTN_FREG(fd, WT2);
|
GEN_STORE_FTN_FREG(fd, WT2);
|
||||||
opn = "recip.s";
|
opn = "recip.s";
|
||||||
break;
|
break;
|
||||||
case FOP(22, 16):
|
case FOP(22, 16):
|
||||||
|
check_cop1x(ctx);
|
||||||
GEN_LOAD_FREG_FTN(WT0, fs);
|
GEN_LOAD_FREG_FTN(WT0, fs);
|
||||||
gen_op_float_rsqrt_s();
|
gen_op_float_rsqrt_s();
|
||||||
GEN_STORE_FTN_FREG(fd, WT2);
|
GEN_STORE_FTN_FREG(fd, WT2);
|
||||||
|
@ -5266,7 +5281,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
|
||||||
GEN_LOAD_FREG_FTN(WT0, fs);
|
GEN_LOAD_FREG_FTN(WT0, fs);
|
||||||
GEN_LOAD_FREG_FTN(WT1, ft);
|
GEN_LOAD_FREG_FTN(WT1, ft);
|
||||||
if (ctx->opcode & (1 << 6)) {
|
if (ctx->opcode & (1 << 6)) {
|
||||||
check_cp1_64bitmode(ctx);
|
check_cop1x(ctx);
|
||||||
gen_cmpabs_s(func-48, cc);
|
gen_cmpabs_s(func-48, cc);
|
||||||
opn = condnames_abs[func-48];
|
opn = condnames_abs[func-48];
|
||||||
} else {
|
} else {
|
||||||
|
@ -5419,14 +5434,14 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
|
||||||
opn = "movn.d";
|
opn = "movn.d";
|
||||||
break;
|
break;
|
||||||
case FOP(21, 17):
|
case FOP(21, 17):
|
||||||
check_cp1_registers(ctx, fs | fd);
|
check_cp1_64bitmode(ctx);
|
||||||
GEN_LOAD_FREG_FTN(DT0, fs);
|
GEN_LOAD_FREG_FTN(DT0, fs);
|
||||||
gen_op_float_recip_d();
|
gen_op_float_recip_d();
|
||||||
GEN_STORE_FTN_FREG(fd, DT2);
|
GEN_STORE_FTN_FREG(fd, DT2);
|
||||||
opn = "recip.d";
|
opn = "recip.d";
|
||||||
break;
|
break;
|
||||||
case FOP(22, 17):
|
case FOP(22, 17):
|
||||||
check_cp1_registers(ctx, fs | fd);
|
check_cp1_64bitmode(ctx);
|
||||||
GEN_LOAD_FREG_FTN(DT0, fs);
|
GEN_LOAD_FREG_FTN(DT0, fs);
|
||||||
gen_op_float_rsqrt_d();
|
gen_op_float_rsqrt_d();
|
||||||
GEN_STORE_FTN_FREG(fd, DT2);
|
GEN_STORE_FTN_FREG(fd, DT2);
|
||||||
|
@ -5481,7 +5496,8 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
|
||||||
GEN_LOAD_FREG_FTN(DT0, fs);
|
GEN_LOAD_FREG_FTN(DT0, fs);
|
||||||
GEN_LOAD_FREG_FTN(DT1, ft);
|
GEN_LOAD_FREG_FTN(DT1, ft);
|
||||||
if (ctx->opcode & (1 << 6)) {
|
if (ctx->opcode & (1 << 6)) {
|
||||||
check_cp1_64bitmode(ctx);
|
check_cop1x(ctx);
|
||||||
|
check_cp1_registers(ctx, fs | ft);
|
||||||
gen_cmpabs_d(func-48, cc);
|
gen_cmpabs_d(func-48, cc);
|
||||||
opn = condnames_abs[func-48];
|
opn = condnames_abs[func-48];
|
||||||
} else {
|
} else {
|
||||||
|
@ -5814,8 +5830,6 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
|
||||||
const char *opn = "extended float load/store";
|
const char *opn = "extended float load/store";
|
||||||
int store = 0;
|
int store = 0;
|
||||||
|
|
||||||
/* All of those work only on 64bit FPUs. */
|
|
||||||
check_cp1_64bitmode(ctx);
|
|
||||||
if (base == 0) {
|
if (base == 0) {
|
||||||
if (index == 0)
|
if (index == 0)
|
||||||
gen_op_reset_T0();
|
gen_op_reset_T0();
|
||||||
|
@ -5832,33 +5846,41 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
|
||||||
memory access. */
|
memory access. */
|
||||||
switch (opc) {
|
switch (opc) {
|
||||||
case OPC_LWXC1:
|
case OPC_LWXC1:
|
||||||
|
check_cop1x(ctx);
|
||||||
op_ldst(lwc1);
|
op_ldst(lwc1);
|
||||||
GEN_STORE_FTN_FREG(fd, WT0);
|
GEN_STORE_FTN_FREG(fd, WT0);
|
||||||
opn = "lwxc1";
|
opn = "lwxc1";
|
||||||
break;
|
break;
|
||||||
case OPC_LDXC1:
|
case OPC_LDXC1:
|
||||||
|
check_cop1x(ctx);
|
||||||
|
check_cp1_registers(ctx, fd);
|
||||||
op_ldst(ldc1);
|
op_ldst(ldc1);
|
||||||
GEN_STORE_FTN_FREG(fd, DT0);
|
GEN_STORE_FTN_FREG(fd, DT0);
|
||||||
opn = "ldxc1";
|
opn = "ldxc1";
|
||||||
break;
|
break;
|
||||||
case OPC_LUXC1:
|
case OPC_LUXC1:
|
||||||
|
check_cp1_64bitmode(ctx);
|
||||||
op_ldst(luxc1);
|
op_ldst(luxc1);
|
||||||
GEN_STORE_FTN_FREG(fd, DT0);
|
GEN_STORE_FTN_FREG(fd, DT0);
|
||||||
opn = "luxc1";
|
opn = "luxc1";
|
||||||
break;
|
break;
|
||||||
case OPC_SWXC1:
|
case OPC_SWXC1:
|
||||||
|
check_cop1x(ctx);
|
||||||
GEN_LOAD_FREG_FTN(WT0, fs);
|
GEN_LOAD_FREG_FTN(WT0, fs);
|
||||||
op_ldst(swc1);
|
op_ldst(swc1);
|
||||||
opn = "swxc1";
|
opn = "swxc1";
|
||||||
store = 1;
|
store = 1;
|
||||||
break;
|
break;
|
||||||
case OPC_SDXC1:
|
case OPC_SDXC1:
|
||||||
|
check_cop1x(ctx);
|
||||||
|
check_cp1_registers(ctx, fs);
|
||||||
GEN_LOAD_FREG_FTN(DT0, fs);
|
GEN_LOAD_FREG_FTN(DT0, fs);
|
||||||
op_ldst(sdc1);
|
op_ldst(sdc1);
|
||||||
opn = "sdxc1";
|
opn = "sdxc1";
|
||||||
store = 1;
|
store = 1;
|
||||||
break;
|
break;
|
||||||
case OPC_SUXC1:
|
case OPC_SUXC1:
|
||||||
|
check_cp1_64bitmode(ctx);
|
||||||
GEN_LOAD_FREG_FTN(DT0, fs);
|
GEN_LOAD_FREG_FTN(DT0, fs);
|
||||||
op_ldst(suxc1);
|
op_ldst(suxc1);
|
||||||
opn = "suxc1";
|
opn = "suxc1";
|
||||||
|
@ -5878,10 +5900,9 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
|
||||||
{
|
{
|
||||||
const char *opn = "flt3_arith";
|
const char *opn = "flt3_arith";
|
||||||
|
|
||||||
/* All of those work only on 64bit FPUs. */
|
|
||||||
check_cp1_64bitmode(ctx);
|
|
||||||
switch (opc) {
|
switch (opc) {
|
||||||
case OPC_ALNV_PS:
|
case OPC_ALNV_PS:
|
||||||
|
check_cp1_64bitmode(ctx);
|
||||||
GEN_LOAD_REG_T0(fr);
|
GEN_LOAD_REG_T0(fr);
|
||||||
GEN_LOAD_FREG_FTN(DT0, fs);
|
GEN_LOAD_FREG_FTN(DT0, fs);
|
||||||
GEN_LOAD_FREG_FTN(DT1, ft);
|
GEN_LOAD_FREG_FTN(DT1, ft);
|
||||||
|
@ -5890,6 +5911,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
|
||||||
opn = "alnv.ps";
|
opn = "alnv.ps";
|
||||||
break;
|
break;
|
||||||
case OPC_MADD_S:
|
case OPC_MADD_S:
|
||||||
|
check_cop1x(ctx);
|
||||||
GEN_LOAD_FREG_FTN(WT0, fs);
|
GEN_LOAD_FREG_FTN(WT0, fs);
|
||||||
GEN_LOAD_FREG_FTN(WT1, ft);
|
GEN_LOAD_FREG_FTN(WT1, ft);
|
||||||
GEN_LOAD_FREG_FTN(WT2, fr);
|
GEN_LOAD_FREG_FTN(WT2, fr);
|
||||||
|
@ -5898,6 +5920,8 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
|
||||||
opn = "madd.s";
|
opn = "madd.s";
|
||||||
break;
|
break;
|
||||||
case OPC_MADD_D:
|
case OPC_MADD_D:
|
||||||
|
check_cop1x(ctx);
|
||||||
|
check_cp1_registers(ctx, fd | fs | ft | fr);
|
||||||
GEN_LOAD_FREG_FTN(DT0, fs);
|
GEN_LOAD_FREG_FTN(DT0, fs);
|
||||||
GEN_LOAD_FREG_FTN(DT1, ft);
|
GEN_LOAD_FREG_FTN(DT1, ft);
|
||||||
GEN_LOAD_FREG_FTN(DT2, fr);
|
GEN_LOAD_FREG_FTN(DT2, fr);
|
||||||
|
@ -5906,6 +5930,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
|
||||||
opn = "madd.d";
|
opn = "madd.d";
|
||||||
break;
|
break;
|
||||||
case OPC_MADD_PS:
|
case OPC_MADD_PS:
|
||||||
|
check_cp1_64bitmode(ctx);
|
||||||
GEN_LOAD_FREG_FTN(WT0, fs);
|
GEN_LOAD_FREG_FTN(WT0, fs);
|
||||||
GEN_LOAD_FREG_FTN(WTH0, fs);
|
GEN_LOAD_FREG_FTN(WTH0, fs);
|
||||||
GEN_LOAD_FREG_FTN(WT1, ft);
|
GEN_LOAD_FREG_FTN(WT1, ft);
|
||||||
|
@ -5918,6 +5943,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
|
||||||
opn = "madd.ps";
|
opn = "madd.ps";
|
||||||
break;
|
break;
|
||||||
case OPC_MSUB_S:
|
case OPC_MSUB_S:
|
||||||
|
check_cop1x(ctx);
|
||||||
GEN_LOAD_FREG_FTN(WT0, fs);
|
GEN_LOAD_FREG_FTN(WT0, fs);
|
||||||
GEN_LOAD_FREG_FTN(WT1, ft);
|
GEN_LOAD_FREG_FTN(WT1, ft);
|
||||||
GEN_LOAD_FREG_FTN(WT2, fr);
|
GEN_LOAD_FREG_FTN(WT2, fr);
|
||||||
|
@ -5926,6 +5952,8 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
|
||||||
opn = "msub.s";
|
opn = "msub.s";
|
||||||
break;
|
break;
|
||||||
case OPC_MSUB_D:
|
case OPC_MSUB_D:
|
||||||
|
check_cop1x(ctx);
|
||||||
|
check_cp1_registers(ctx, fd | fs | ft | fr);
|
||||||
GEN_LOAD_FREG_FTN(DT0, fs);
|
GEN_LOAD_FREG_FTN(DT0, fs);
|
||||||
GEN_LOAD_FREG_FTN(DT1, ft);
|
GEN_LOAD_FREG_FTN(DT1, ft);
|
||||||
GEN_LOAD_FREG_FTN(DT2, fr);
|
GEN_LOAD_FREG_FTN(DT2, fr);
|
||||||
|
@ -5934,6 +5962,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
|
||||||
opn = "msub.d";
|
opn = "msub.d";
|
||||||
break;
|
break;
|
||||||
case OPC_MSUB_PS:
|
case OPC_MSUB_PS:
|
||||||
|
check_cp1_64bitmode(ctx);
|
||||||
GEN_LOAD_FREG_FTN(WT0, fs);
|
GEN_LOAD_FREG_FTN(WT0, fs);
|
||||||
GEN_LOAD_FREG_FTN(WTH0, fs);
|
GEN_LOAD_FREG_FTN(WTH0, fs);
|
||||||
GEN_LOAD_FREG_FTN(WT1, ft);
|
GEN_LOAD_FREG_FTN(WT1, ft);
|
||||||
|
@ -5946,6 +5975,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
|
||||||
opn = "msub.ps";
|
opn = "msub.ps";
|
||||||
break;
|
break;
|
||||||
case OPC_NMADD_S:
|
case OPC_NMADD_S:
|
||||||
|
check_cop1x(ctx);
|
||||||
GEN_LOAD_FREG_FTN(WT0, fs);
|
GEN_LOAD_FREG_FTN(WT0, fs);
|
||||||
GEN_LOAD_FREG_FTN(WT1, ft);
|
GEN_LOAD_FREG_FTN(WT1, ft);
|
||||||
GEN_LOAD_FREG_FTN(WT2, fr);
|
GEN_LOAD_FREG_FTN(WT2, fr);
|
||||||
|
@ -5954,6 +5984,8 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
|
||||||
opn = "nmadd.s";
|
opn = "nmadd.s";
|
||||||
break;
|
break;
|
||||||
case OPC_NMADD_D:
|
case OPC_NMADD_D:
|
||||||
|
check_cop1x(ctx);
|
||||||
|
check_cp1_registers(ctx, fd | fs | ft | fr);
|
||||||
GEN_LOAD_FREG_FTN(DT0, fs);
|
GEN_LOAD_FREG_FTN(DT0, fs);
|
||||||
GEN_LOAD_FREG_FTN(DT1, ft);
|
GEN_LOAD_FREG_FTN(DT1, ft);
|
||||||
GEN_LOAD_FREG_FTN(DT2, fr);
|
GEN_LOAD_FREG_FTN(DT2, fr);
|
||||||
|
@ -5962,6 +5994,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
|
||||||
opn = "nmadd.d";
|
opn = "nmadd.d";
|
||||||
break;
|
break;
|
||||||
case OPC_NMADD_PS:
|
case OPC_NMADD_PS:
|
||||||
|
check_cp1_64bitmode(ctx);
|
||||||
GEN_LOAD_FREG_FTN(WT0, fs);
|
GEN_LOAD_FREG_FTN(WT0, fs);
|
||||||
GEN_LOAD_FREG_FTN(WTH0, fs);
|
GEN_LOAD_FREG_FTN(WTH0, fs);
|
||||||
GEN_LOAD_FREG_FTN(WT1, ft);
|
GEN_LOAD_FREG_FTN(WT1, ft);
|
||||||
|
@ -5974,6 +6007,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
|
||||||
opn = "nmadd.ps";
|
opn = "nmadd.ps";
|
||||||
break;
|
break;
|
||||||
case OPC_NMSUB_S:
|
case OPC_NMSUB_S:
|
||||||
|
check_cop1x(ctx);
|
||||||
GEN_LOAD_FREG_FTN(WT0, fs);
|
GEN_LOAD_FREG_FTN(WT0, fs);
|
||||||
GEN_LOAD_FREG_FTN(WT1, ft);
|
GEN_LOAD_FREG_FTN(WT1, ft);
|
||||||
GEN_LOAD_FREG_FTN(WT2, fr);
|
GEN_LOAD_FREG_FTN(WT2, fr);
|
||||||
|
@ -5982,6 +6016,8 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
|
||||||
opn = "nmsub.s";
|
opn = "nmsub.s";
|
||||||
break;
|
break;
|
||||||
case OPC_NMSUB_D:
|
case OPC_NMSUB_D:
|
||||||
|
check_cop1x(ctx);
|
||||||
|
check_cp1_registers(ctx, fd | fs | ft | fr);
|
||||||
GEN_LOAD_FREG_FTN(DT0, fs);
|
GEN_LOAD_FREG_FTN(DT0, fs);
|
||||||
GEN_LOAD_FREG_FTN(DT1, ft);
|
GEN_LOAD_FREG_FTN(DT1, ft);
|
||||||
GEN_LOAD_FREG_FTN(DT2, fr);
|
GEN_LOAD_FREG_FTN(DT2, fr);
|
||||||
|
@ -5990,6 +6026,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
|
||||||
opn = "nmsub.d";
|
opn = "nmsub.d";
|
||||||
break;
|
break;
|
||||||
case OPC_NMSUB_PS:
|
case OPC_NMSUB_PS:
|
||||||
|
check_cp1_64bitmode(ctx);
|
||||||
GEN_LOAD_FREG_FTN(WT0, fs);
|
GEN_LOAD_FREG_FTN(WT0, fs);
|
||||||
GEN_LOAD_FREG_FTN(WTH0, fs);
|
GEN_LOAD_FREG_FTN(WTH0, fs);
|
||||||
GEN_LOAD_FREG_FTN(WT1, ft);
|
GEN_LOAD_FREG_FTN(WT1, ft);
|
||||||
|
@ -6465,6 +6502,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
|
||||||
#endif
|
#endif
|
||||||
case OPC_BC1ANY2:
|
case OPC_BC1ANY2:
|
||||||
case OPC_BC1ANY4:
|
case OPC_BC1ANY4:
|
||||||
|
check_cop1x(ctx);
|
||||||
check_insn(env, ctx, ASE_MIPS3D);
|
check_insn(env, ctx, ASE_MIPS3D);
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case OPC_BC1:
|
case OPC_BC1:
|
||||||
|
|
Loading…
Reference in New Issue