Commit b8aa4598e2cc109b0884740a42116acaab01e67d

Authored by ths
1 parent 6341fdcb

MIPS COP1X (and related) instructions, by Richard Sandiford.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3877 c046a42c-6fe2-441c-8c8c-71466251a162
target-mips/cpu.h
@@ -417,7 +417,7 @@ struct CPUMIPSState { @@ -417,7 +417,7 @@ struct CPUMIPSState {
417 int user_mode_only; /* user mode only simulation */ 417 int user_mode_only; /* user mode only simulation */
418 uint32_t hflags; /* CPU State */ 418 uint32_t hflags; /* CPU State */
419 /* TMASK defines different execution modes */ 419 /* TMASK defines different execution modes */
420 -#define MIPS_HFLAG_TMASK 0x00FF 420 +#define MIPS_HFLAG_TMASK 0x01FF
421 #define MIPS_HFLAG_MODE 0x0007 /* execution modes */ 421 #define MIPS_HFLAG_MODE 0x0007 /* execution modes */
422 /* The KSU flags must be the lowest bits in hflags. The flag order 422 /* The KSU flags must be the lowest bits in hflags. The flag order
423 must be the same as defined for CP0 Status. This allows to use 423 must be the same as defined for CP0 Status. This allows to use
@@ -431,16 +431,20 @@ struct CPUMIPSState { @@ -431,16 +431,20 @@ struct CPUMIPSState {
431 #define MIPS_HFLAG_CP0 0x0010 /* CP0 enabled */ 431 #define MIPS_HFLAG_CP0 0x0010 /* CP0 enabled */
432 #define MIPS_HFLAG_FPU 0x0020 /* FPU enabled */ 432 #define MIPS_HFLAG_FPU 0x0020 /* FPU enabled */
433 #define MIPS_HFLAG_F64 0x0040 /* 64-bit FPU enabled */ 433 #define MIPS_HFLAG_F64 0x0040 /* 64-bit FPU enabled */
434 -#define MIPS_HFLAG_RE 0x0080 /* Reversed endianness */ 434 + /* True if the MIPS IV COP1X instructions can be used. This also
  435 + controls the non-COP1X instructions RECIP.S, RECIP.D, RSQRT.S
  436 + and RSQRT.D. */
  437 +#define MIPS_HFLAG_COP1X 0x0080 /* COP1X instructions enabled */
  438 +#define MIPS_HFLAG_RE 0x0100 /* Reversed endianness */
435 /* If translation is interrupted between the branch instruction and 439 /* If translation is interrupted between the branch instruction and
436 * the delay slot, record what type of branch it is so that we can 440 * the delay slot, record what type of branch it is so that we can
437 * resume translation properly. It might be possible to reduce 441 * resume translation properly. It might be possible to reduce
438 * this from three bits to two. */ 442 * this from three bits to two. */
439 -#define MIPS_HFLAG_BMASK 0x0700  
440 -#define MIPS_HFLAG_B 0x0100 /* Unconditional branch */  
441 -#define MIPS_HFLAG_BC 0x0200 /* Conditional branch */  
442 -#define MIPS_HFLAG_BL 0x0300 /* Likely branch */  
443 -#define MIPS_HFLAG_BR 0x0400 /* branch to register (can't link TB) */ 443 +#define MIPS_HFLAG_BMASK 0x0e00
  444 +#define MIPS_HFLAG_B 0x0200 /* Unconditional branch */
  445 +#define MIPS_HFLAG_BC 0x0400 /* Conditional branch */
  446 +#define MIPS_HFLAG_BL 0x0600 /* Likely branch */
  447 +#define MIPS_HFLAG_BR 0x0800 /* branch to register (can't link TB) */
444 target_ulong btarget; /* Jump / branch target */ 448 target_ulong btarget; /* Jump / branch target */
445 int bcond; /* Branch condition (if needed) */ 449 int bcond; /* Branch condition (if needed) */
446 450
target-mips/exec.h
@@ -237,8 +237,8 @@ static always_inline int cpu_halted(CPUState *env) @@ -237,8 +237,8 @@ static always_inline int cpu_halted(CPUState *env)
237 237
238 static always_inline void compute_hflags(CPUState *env) 238 static always_inline void compute_hflags(CPUState *env)
239 { 239 {
240 - env->hflags &= ~(MIPS_HFLAG_64 | MIPS_HFLAG_CP0 | MIPS_HFLAG_F64 |  
241 - MIPS_HFLAG_FPU | MIPS_HFLAG_KSU); 240 + env->hflags &= ~(MIPS_HFLAG_COP1X | MIPS_HFLAG_64 | MIPS_HFLAG_CP0 |
  241 + MIPS_HFLAG_F64 | MIPS_HFLAG_FPU | MIPS_HFLAG_KSU);
242 if (!(env->CP0_Status & (1 << CP0St_EXL)) && 242 if (!(env->CP0_Status & (1 << CP0St_EXL)) &&
243 !(env->CP0_Status & (1 << CP0St_ERL)) && 243 !(env->CP0_Status & (1 << CP0St_ERL)) &&
244 !(env->hflags & MIPS_HFLAG_DM)) { 244 !(env->hflags & MIPS_HFLAG_DM)) {
@@ -257,6 +257,20 @@ static always_inline void compute_hflags(CPUState *env) @@ -257,6 +257,20 @@ static always_inline void compute_hflags(CPUState *env)
257 env->hflags |= MIPS_HFLAG_FPU; 257 env->hflags |= MIPS_HFLAG_FPU;
258 if (env->CP0_Status & (1 << CP0St_FR)) 258 if (env->CP0_Status & (1 << CP0St_FR))
259 env->hflags |= MIPS_HFLAG_F64; 259 env->hflags |= MIPS_HFLAG_F64;
  260 + if (env->insn_flags & ISA_MIPS32R2) {
  261 + if (env->fpu->fcr0 & FCR0_F64)
  262 + env->hflags |= MIPS_HFLAG_COP1X;
  263 + } else if (env->insn_flags & ISA_MIPS32) {
  264 + if (env->hflags & MIPS_HFLAG_64)
  265 + env->hflags |= MIPS_HFLAG_COP1X;
  266 + } else if (env->insn_flags & ISA_MIPS4) {
  267 + /* All supported MIPS IV CPUs use the XX (CU3) to enable
  268 + and disable the MIPS IV extensions to the MIPS III ISA.
  269 + Some other MIPS IV CPUs ignore the bit, so the check here
  270 + would be too restrictive for them. */
  271 + if (env->CP0_Status & (1 << CP0St_CU3))
  272 + env->hflags |= MIPS_HFLAG_COP1X;
  273 + }
260 } 274 }
261 275
262 #endif /* !defined(__QEMU_MIPS_EXEC_H__) */ 276 #endif /* !defined(__QEMU_MIPS_EXEC_H__) */
target-mips/translate.c
@@ -794,9 +794,22 @@ static always_inline void check_cp1_enabled(DisasContext *ctx) @@ -794,9 +794,22 @@ static always_inline void check_cp1_enabled(DisasContext *ctx)
794 generate_exception_err(ctx, EXCP_CpU, 1); 794 generate_exception_err(ctx, EXCP_CpU, 1);
795 } 795 }
796 796
  797 +/* Verify that the processor is running with COP1X instructions enabled.
  798 + This is associated with the nabla symbol in the MIPS32 and MIPS64
  799 + opcode tables. */
  800 +
  801 +static always_inline void check_cop1x(DisasContext *ctx)
  802 +{
  803 + if (unlikely(!(ctx->hflags & MIPS_HFLAG_COP1X)))
  804 + generate_exception(ctx, EXCP_RI);
  805 +}
  806 +
  807 +/* Verify that the processor is running with 64-bit floating-point
  808 + operations enabled. */
  809 +
797 static always_inline void check_cp1_64bitmode(DisasContext *ctx) 810 static always_inline void check_cp1_64bitmode(DisasContext *ctx)
798 { 811 {
799 - if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64))) 812 + if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
800 generate_exception(ctx, EXCP_RI); 813 generate_exception(ctx, EXCP_RI);
801 } 814 }
802 815
@@ -5178,12 +5191,14 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, @@ -5178,12 +5191,14 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
5178 opn = "movn.s"; 5191 opn = "movn.s";
5179 break; 5192 break;
5180 case FOP(21, 16): 5193 case FOP(21, 16):
  5194 + check_cop1x(ctx);
5181 GEN_LOAD_FREG_FTN(WT0, fs); 5195 GEN_LOAD_FREG_FTN(WT0, fs);
5182 gen_op_float_recip_s(); 5196 gen_op_float_recip_s();
5183 GEN_STORE_FTN_FREG(fd, WT2); 5197 GEN_STORE_FTN_FREG(fd, WT2);
5184 opn = "recip.s"; 5198 opn = "recip.s";
5185 break; 5199 break;
5186 case FOP(22, 16): 5200 case FOP(22, 16):
  5201 + check_cop1x(ctx);
5187 GEN_LOAD_FREG_FTN(WT0, fs); 5202 GEN_LOAD_FREG_FTN(WT0, fs);
5188 gen_op_float_rsqrt_s(); 5203 gen_op_float_rsqrt_s();
5189 GEN_STORE_FTN_FREG(fd, WT2); 5204 GEN_STORE_FTN_FREG(fd, WT2);
@@ -5266,7 +5281,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, @@ -5266,7 +5281,7 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
5266 GEN_LOAD_FREG_FTN(WT0, fs); 5281 GEN_LOAD_FREG_FTN(WT0, fs);
5267 GEN_LOAD_FREG_FTN(WT1, ft); 5282 GEN_LOAD_FREG_FTN(WT1, ft);
5268 if (ctx->opcode & (1 << 6)) { 5283 if (ctx->opcode & (1 << 6)) {
5269 - check_cp1_64bitmode(ctx); 5284 + check_cop1x(ctx);
5270 gen_cmpabs_s(func-48, cc); 5285 gen_cmpabs_s(func-48, cc);
5271 opn = condnames_abs[func-48]; 5286 opn = condnames_abs[func-48];
5272 } else { 5287 } else {
@@ -5419,14 +5434,14 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, @@ -5419,14 +5434,14 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
5419 opn = "movn.d"; 5434 opn = "movn.d";
5420 break; 5435 break;
5421 case FOP(21, 17): 5436 case FOP(21, 17):
5422 - check_cp1_registers(ctx, fs | fd); 5437 + check_cp1_64bitmode(ctx);
5423 GEN_LOAD_FREG_FTN(DT0, fs); 5438 GEN_LOAD_FREG_FTN(DT0, fs);
5424 gen_op_float_recip_d(); 5439 gen_op_float_recip_d();
5425 GEN_STORE_FTN_FREG(fd, DT2); 5440 GEN_STORE_FTN_FREG(fd, DT2);
5426 opn = "recip.d"; 5441 opn = "recip.d";
5427 break; 5442 break;
5428 case FOP(22, 17): 5443 case FOP(22, 17):
5429 - check_cp1_registers(ctx, fs | fd); 5444 + check_cp1_64bitmode(ctx);
5430 GEN_LOAD_FREG_FTN(DT0, fs); 5445 GEN_LOAD_FREG_FTN(DT0, fs);
5431 gen_op_float_rsqrt_d(); 5446 gen_op_float_rsqrt_d();
5432 GEN_STORE_FTN_FREG(fd, DT2); 5447 GEN_STORE_FTN_FREG(fd, DT2);
@@ -5481,7 +5496,8 @@ static void gen_farith (DisasContext *ctx, uint32_t op1, @@ -5481,7 +5496,8 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
5481 GEN_LOAD_FREG_FTN(DT0, fs); 5496 GEN_LOAD_FREG_FTN(DT0, fs);
5482 GEN_LOAD_FREG_FTN(DT1, ft); 5497 GEN_LOAD_FREG_FTN(DT1, ft);
5483 if (ctx->opcode & (1 << 6)) { 5498 if (ctx->opcode & (1 << 6)) {
5484 - check_cp1_64bitmode(ctx); 5499 + check_cop1x(ctx);
  5500 + check_cp1_registers(ctx, fs | ft);
5485 gen_cmpabs_d(func-48, cc); 5501 gen_cmpabs_d(func-48, cc);
5486 opn = condnames_abs[func-48]; 5502 opn = condnames_abs[func-48];
5487 } else { 5503 } else {
@@ -5814,8 +5830,6 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, @@ -5814,8 +5830,6 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
5814 const char *opn = "extended float load/store"; 5830 const char *opn = "extended float load/store";
5815 int store = 0; 5831 int store = 0;
5816 5832
5817 - /* All of those work only on 64bit FPUs. */  
5818 - check_cp1_64bitmode(ctx);  
5819 if (base == 0) { 5833 if (base == 0) {
5820 if (index == 0) 5834 if (index == 0)
5821 gen_op_reset_T0(); 5835 gen_op_reset_T0();
@@ -5832,33 +5846,41 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc, @@ -5832,33 +5846,41 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
5832 memory access. */ 5846 memory access. */
5833 switch (opc) { 5847 switch (opc) {
5834 case OPC_LWXC1: 5848 case OPC_LWXC1:
  5849 + check_cop1x(ctx);
5835 op_ldst(lwc1); 5850 op_ldst(lwc1);
5836 GEN_STORE_FTN_FREG(fd, WT0); 5851 GEN_STORE_FTN_FREG(fd, WT0);
5837 opn = "lwxc1"; 5852 opn = "lwxc1";
5838 break; 5853 break;
5839 case OPC_LDXC1: 5854 case OPC_LDXC1:
  5855 + check_cop1x(ctx);
  5856 + check_cp1_registers(ctx, fd);
5840 op_ldst(ldc1); 5857 op_ldst(ldc1);
5841 GEN_STORE_FTN_FREG(fd, DT0); 5858 GEN_STORE_FTN_FREG(fd, DT0);
5842 opn = "ldxc1"; 5859 opn = "ldxc1";
5843 break; 5860 break;
5844 case OPC_LUXC1: 5861 case OPC_LUXC1:
  5862 + check_cp1_64bitmode(ctx);
5845 op_ldst(luxc1); 5863 op_ldst(luxc1);
5846 GEN_STORE_FTN_FREG(fd, DT0); 5864 GEN_STORE_FTN_FREG(fd, DT0);
5847 opn = "luxc1"; 5865 opn = "luxc1";
5848 break; 5866 break;
5849 case OPC_SWXC1: 5867 case OPC_SWXC1:
  5868 + check_cop1x(ctx);
5850 GEN_LOAD_FREG_FTN(WT0, fs); 5869 GEN_LOAD_FREG_FTN(WT0, fs);
5851 op_ldst(swc1); 5870 op_ldst(swc1);
5852 opn = "swxc1"; 5871 opn = "swxc1";
5853 store = 1; 5872 store = 1;
5854 break; 5873 break;
5855 case OPC_SDXC1: 5874 case OPC_SDXC1:
  5875 + check_cop1x(ctx);
  5876 + check_cp1_registers(ctx, fs);
5856 GEN_LOAD_FREG_FTN(DT0, fs); 5877 GEN_LOAD_FREG_FTN(DT0, fs);
5857 op_ldst(sdc1); 5878 op_ldst(sdc1);
5858 opn = "sdxc1"; 5879 opn = "sdxc1";
5859 store = 1; 5880 store = 1;
5860 break; 5881 break;
5861 case OPC_SUXC1: 5882 case OPC_SUXC1:
  5883 + check_cp1_64bitmode(ctx);
5862 GEN_LOAD_FREG_FTN(DT0, fs); 5884 GEN_LOAD_FREG_FTN(DT0, fs);
5863 op_ldst(suxc1); 5885 op_ldst(suxc1);
5864 opn = "suxc1"; 5886 opn = "suxc1";
@@ -5878,10 +5900,9 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, @@ -5878,10 +5900,9 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
5878 { 5900 {
5879 const char *opn = "flt3_arith"; 5901 const char *opn = "flt3_arith";
5880 5902
5881 - /* All of those work only on 64bit FPUs. */  
5882 - check_cp1_64bitmode(ctx);  
5883 switch (opc) { 5903 switch (opc) {
5884 case OPC_ALNV_PS: 5904 case OPC_ALNV_PS:
  5905 + check_cp1_64bitmode(ctx);
5885 GEN_LOAD_REG_T0(fr); 5906 GEN_LOAD_REG_T0(fr);
5886 GEN_LOAD_FREG_FTN(DT0, fs); 5907 GEN_LOAD_FREG_FTN(DT0, fs);
5887 GEN_LOAD_FREG_FTN(DT1, ft); 5908 GEN_LOAD_FREG_FTN(DT1, ft);
@@ -5890,6 +5911,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, @@ -5890,6 +5911,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
5890 opn = "alnv.ps"; 5911 opn = "alnv.ps";
5891 break; 5912 break;
5892 case OPC_MADD_S: 5913 case OPC_MADD_S:
  5914 + check_cop1x(ctx);
5893 GEN_LOAD_FREG_FTN(WT0, fs); 5915 GEN_LOAD_FREG_FTN(WT0, fs);
5894 GEN_LOAD_FREG_FTN(WT1, ft); 5916 GEN_LOAD_FREG_FTN(WT1, ft);
5895 GEN_LOAD_FREG_FTN(WT2, fr); 5917 GEN_LOAD_FREG_FTN(WT2, fr);
@@ -5898,6 +5920,8 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, @@ -5898,6 +5920,8 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
5898 opn = "madd.s"; 5920 opn = "madd.s";
5899 break; 5921 break;
5900 case OPC_MADD_D: 5922 case OPC_MADD_D:
  5923 + check_cop1x(ctx);
  5924 + check_cp1_registers(ctx, fd | fs | ft | fr);
5901 GEN_LOAD_FREG_FTN(DT0, fs); 5925 GEN_LOAD_FREG_FTN(DT0, fs);
5902 GEN_LOAD_FREG_FTN(DT1, ft); 5926 GEN_LOAD_FREG_FTN(DT1, ft);
5903 GEN_LOAD_FREG_FTN(DT2, fr); 5927 GEN_LOAD_FREG_FTN(DT2, fr);
@@ -5906,6 +5930,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, @@ -5906,6 +5930,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
5906 opn = "madd.d"; 5930 opn = "madd.d";
5907 break; 5931 break;
5908 case OPC_MADD_PS: 5932 case OPC_MADD_PS:
  5933 + check_cp1_64bitmode(ctx);
5909 GEN_LOAD_FREG_FTN(WT0, fs); 5934 GEN_LOAD_FREG_FTN(WT0, fs);
5910 GEN_LOAD_FREG_FTN(WTH0, fs); 5935 GEN_LOAD_FREG_FTN(WTH0, fs);
5911 GEN_LOAD_FREG_FTN(WT1, ft); 5936 GEN_LOAD_FREG_FTN(WT1, ft);
@@ -5918,6 +5943,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, @@ -5918,6 +5943,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
5918 opn = "madd.ps"; 5943 opn = "madd.ps";
5919 break; 5944 break;
5920 case OPC_MSUB_S: 5945 case OPC_MSUB_S:
  5946 + check_cop1x(ctx);
5921 GEN_LOAD_FREG_FTN(WT0, fs); 5947 GEN_LOAD_FREG_FTN(WT0, fs);
5922 GEN_LOAD_FREG_FTN(WT1, ft); 5948 GEN_LOAD_FREG_FTN(WT1, ft);
5923 GEN_LOAD_FREG_FTN(WT2, fr); 5949 GEN_LOAD_FREG_FTN(WT2, fr);
@@ -5926,6 +5952,8 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, @@ -5926,6 +5952,8 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
5926 opn = "msub.s"; 5952 opn = "msub.s";
5927 break; 5953 break;
5928 case OPC_MSUB_D: 5954 case OPC_MSUB_D:
  5955 + check_cop1x(ctx);
  5956 + check_cp1_registers(ctx, fd | fs | ft | fr);
5929 GEN_LOAD_FREG_FTN(DT0, fs); 5957 GEN_LOAD_FREG_FTN(DT0, fs);
5930 GEN_LOAD_FREG_FTN(DT1, ft); 5958 GEN_LOAD_FREG_FTN(DT1, ft);
5931 GEN_LOAD_FREG_FTN(DT2, fr); 5959 GEN_LOAD_FREG_FTN(DT2, fr);
@@ -5934,6 +5962,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, @@ -5934,6 +5962,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
5934 opn = "msub.d"; 5962 opn = "msub.d";
5935 break; 5963 break;
5936 case OPC_MSUB_PS: 5964 case OPC_MSUB_PS:
  5965 + check_cp1_64bitmode(ctx);
5937 GEN_LOAD_FREG_FTN(WT0, fs); 5966 GEN_LOAD_FREG_FTN(WT0, fs);
5938 GEN_LOAD_FREG_FTN(WTH0, fs); 5967 GEN_LOAD_FREG_FTN(WTH0, fs);
5939 GEN_LOAD_FREG_FTN(WT1, ft); 5968 GEN_LOAD_FREG_FTN(WT1, ft);
@@ -5946,6 +5975,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, @@ -5946,6 +5975,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
5946 opn = "msub.ps"; 5975 opn = "msub.ps";
5947 break; 5976 break;
5948 case OPC_NMADD_S: 5977 case OPC_NMADD_S:
  5978 + check_cop1x(ctx);
5949 GEN_LOAD_FREG_FTN(WT0, fs); 5979 GEN_LOAD_FREG_FTN(WT0, fs);
5950 GEN_LOAD_FREG_FTN(WT1, ft); 5980 GEN_LOAD_FREG_FTN(WT1, ft);
5951 GEN_LOAD_FREG_FTN(WT2, fr); 5981 GEN_LOAD_FREG_FTN(WT2, fr);
@@ -5954,6 +5984,8 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, @@ -5954,6 +5984,8 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
5954 opn = "nmadd.s"; 5984 opn = "nmadd.s";
5955 break; 5985 break;
5956 case OPC_NMADD_D: 5986 case OPC_NMADD_D:
  5987 + check_cop1x(ctx);
  5988 + check_cp1_registers(ctx, fd | fs | ft | fr);
5957 GEN_LOAD_FREG_FTN(DT0, fs); 5989 GEN_LOAD_FREG_FTN(DT0, fs);
5958 GEN_LOAD_FREG_FTN(DT1, ft); 5990 GEN_LOAD_FREG_FTN(DT1, ft);
5959 GEN_LOAD_FREG_FTN(DT2, fr); 5991 GEN_LOAD_FREG_FTN(DT2, fr);
@@ -5962,6 +5994,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, @@ -5962,6 +5994,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
5962 opn = "nmadd.d"; 5994 opn = "nmadd.d";
5963 break; 5995 break;
5964 case OPC_NMADD_PS: 5996 case OPC_NMADD_PS:
  5997 + check_cp1_64bitmode(ctx);
5965 GEN_LOAD_FREG_FTN(WT0, fs); 5998 GEN_LOAD_FREG_FTN(WT0, fs);
5966 GEN_LOAD_FREG_FTN(WTH0, fs); 5999 GEN_LOAD_FREG_FTN(WTH0, fs);
5967 GEN_LOAD_FREG_FTN(WT1, ft); 6000 GEN_LOAD_FREG_FTN(WT1, ft);
@@ -5974,6 +6007,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, @@ -5974,6 +6007,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
5974 opn = "nmadd.ps"; 6007 opn = "nmadd.ps";
5975 break; 6008 break;
5976 case OPC_NMSUB_S: 6009 case OPC_NMSUB_S:
  6010 + check_cop1x(ctx);
5977 GEN_LOAD_FREG_FTN(WT0, fs); 6011 GEN_LOAD_FREG_FTN(WT0, fs);
5978 GEN_LOAD_FREG_FTN(WT1, ft); 6012 GEN_LOAD_FREG_FTN(WT1, ft);
5979 GEN_LOAD_FREG_FTN(WT2, fr); 6013 GEN_LOAD_FREG_FTN(WT2, fr);
@@ -5982,6 +6016,8 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, @@ -5982,6 +6016,8 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
5982 opn = "nmsub.s"; 6016 opn = "nmsub.s";
5983 break; 6017 break;
5984 case OPC_NMSUB_D: 6018 case OPC_NMSUB_D:
  6019 + check_cop1x(ctx);
  6020 + check_cp1_registers(ctx, fd | fs | ft | fr);
5985 GEN_LOAD_FREG_FTN(DT0, fs); 6021 GEN_LOAD_FREG_FTN(DT0, fs);
5986 GEN_LOAD_FREG_FTN(DT1, ft); 6022 GEN_LOAD_FREG_FTN(DT1, ft);
5987 GEN_LOAD_FREG_FTN(DT2, fr); 6023 GEN_LOAD_FREG_FTN(DT2, fr);
@@ -5990,6 +6026,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc, @@ -5990,6 +6026,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
5990 opn = "nmsub.d"; 6026 opn = "nmsub.d";
5991 break; 6027 break;
5992 case OPC_NMSUB_PS: 6028 case OPC_NMSUB_PS:
  6029 + check_cp1_64bitmode(ctx);
5993 GEN_LOAD_FREG_FTN(WT0, fs); 6030 GEN_LOAD_FREG_FTN(WT0, fs);
5994 GEN_LOAD_FREG_FTN(WTH0, fs); 6031 GEN_LOAD_FREG_FTN(WTH0, fs);
5995 GEN_LOAD_FREG_FTN(WT1, ft); 6032 GEN_LOAD_FREG_FTN(WT1, ft);
@@ -6465,6 +6502,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx) @@ -6465,6 +6502,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
6465 #endif 6502 #endif
6466 case OPC_BC1ANY2: 6503 case OPC_BC1ANY2:
6467 case OPC_BC1ANY4: 6504 case OPC_BC1ANY4:
  6505 + check_cop1x(ctx);
6468 check_insn(env, ctx, ASE_MIPS3D); 6506 check_insn(env, ctx, ASE_MIPS3D);
6469 /* fall through */ 6507 /* fall through */
6470 case OPC_BC1: 6508 case OPC_BC1: