aboutsummaryrefslogtreecommitdiff
path: root/target-mips/translate.c
diff options
context:
space:
mode:
Diffstat (limited to 'target-mips/translate.c')
-rw-r--r--target-mips/translate.c56
1 files changed, 47 insertions, 9 deletions
diff --git a/target-mips/translate.c b/target-mips/translate.c
index 1d8aea185b..719af3ae8f 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -794,9 +794,22 @@ static always_inline void check_cp1_enabled(DisasContext *ctx)
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)
{
- if (unlikely(!(ctx->hflags & MIPS_HFLAG_F64)))
+ if (unlikely(~ctx->hflags & (MIPS_HFLAG_F64 | MIPS_HFLAG_COP1X)))
generate_exception(ctx, EXCP_RI);
}
@@ -5178,12 +5191,14 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
opn = "movn.s";
break;
case FOP(21, 16):
+ check_cop1x(ctx);
GEN_LOAD_FREG_FTN(WT0, fs);
gen_op_float_recip_s();
GEN_STORE_FTN_FREG(fd, WT2);
opn = "recip.s";
break;
case FOP(22, 16):
+ check_cop1x(ctx);
GEN_LOAD_FREG_FTN(WT0, fs);
gen_op_float_rsqrt_s();
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(WT1, ft);
if (ctx->opcode & (1 << 6)) {
- check_cp1_64bitmode(ctx);
+ check_cop1x(ctx);
gen_cmpabs_s(func-48, cc);
opn = condnames_abs[func-48];
} else {
@@ -5419,14 +5434,14 @@ static void gen_farith (DisasContext *ctx, uint32_t op1,
opn = "movn.d";
break;
case FOP(21, 17):
- check_cp1_registers(ctx, fs | fd);
+ check_cp1_64bitmode(ctx);
GEN_LOAD_FREG_FTN(DT0, fs);
gen_op_float_recip_d();
GEN_STORE_FTN_FREG(fd, DT2);
opn = "recip.d";
break;
case FOP(22, 17):
- check_cp1_registers(ctx, fs | fd);
+ check_cp1_64bitmode(ctx);
GEN_LOAD_FREG_FTN(DT0, fs);
gen_op_float_rsqrt_d();
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(DT1, ft);
if (ctx->opcode & (1 << 6)) {
- check_cp1_64bitmode(ctx);
+ check_cop1x(ctx);
+ check_cp1_registers(ctx, fs | ft);
gen_cmpabs_d(func-48, cc);
opn = condnames_abs[func-48];
} else {
@@ -5814,8 +5830,6 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
const char *opn = "extended float load/store";
int store = 0;
- /* All of those work only on 64bit FPUs. */
- check_cp1_64bitmode(ctx);
if (base == 0) {
if (index == 0)
gen_op_reset_T0();
@@ -5832,33 +5846,41 @@ static void gen_flt3_ldst (DisasContext *ctx, uint32_t opc,
memory access. */
switch (opc) {
case OPC_LWXC1:
+ check_cop1x(ctx);
op_ldst(lwc1);
GEN_STORE_FTN_FREG(fd, WT0);
opn = "lwxc1";
break;
case OPC_LDXC1:
+ check_cop1x(ctx);
+ check_cp1_registers(ctx, fd);
op_ldst(ldc1);
GEN_STORE_FTN_FREG(fd, DT0);
opn = "ldxc1";
break;
case OPC_LUXC1:
+ check_cp1_64bitmode(ctx);
op_ldst(luxc1);
GEN_STORE_FTN_FREG(fd, DT0);
opn = "luxc1";
break;
case OPC_SWXC1:
+ check_cop1x(ctx);
GEN_LOAD_FREG_FTN(WT0, fs);
op_ldst(swc1);
opn = "swxc1";
store = 1;
break;
case OPC_SDXC1:
+ check_cop1x(ctx);
+ check_cp1_registers(ctx, fs);
GEN_LOAD_FREG_FTN(DT0, fs);
op_ldst(sdc1);
opn = "sdxc1";
store = 1;
break;
case OPC_SUXC1:
+ check_cp1_64bitmode(ctx);
GEN_LOAD_FREG_FTN(DT0, fs);
op_ldst(suxc1);
opn = "suxc1";
@@ -5878,10 +5900,9 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
{
const char *opn = "flt3_arith";
- /* All of those work only on 64bit FPUs. */
- check_cp1_64bitmode(ctx);
switch (opc) {
case OPC_ALNV_PS:
+ check_cp1_64bitmode(ctx);
GEN_LOAD_REG_T0(fr);
GEN_LOAD_FREG_FTN(DT0, fs);
GEN_LOAD_FREG_FTN(DT1, ft);
@@ -5890,6 +5911,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
opn = "alnv.ps";
break;
case OPC_MADD_S:
+ check_cop1x(ctx);
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WT1, ft);
GEN_LOAD_FREG_FTN(WT2, fr);
@@ -5898,6 +5920,8 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
opn = "madd.s";
break;
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(DT1, ft);
GEN_LOAD_FREG_FTN(DT2, fr);
@@ -5906,6 +5930,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
opn = "madd.d";
break;
case OPC_MADD_PS:
+ check_cp1_64bitmode(ctx);
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs);
GEN_LOAD_FREG_FTN(WT1, ft);
@@ -5918,6 +5943,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
opn = "madd.ps";
break;
case OPC_MSUB_S:
+ check_cop1x(ctx);
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WT1, ft);
GEN_LOAD_FREG_FTN(WT2, fr);
@@ -5926,6 +5952,8 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
opn = "msub.s";
break;
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(DT1, ft);
GEN_LOAD_FREG_FTN(DT2, fr);
@@ -5934,6 +5962,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
opn = "msub.d";
break;
case OPC_MSUB_PS:
+ check_cp1_64bitmode(ctx);
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs);
GEN_LOAD_FREG_FTN(WT1, ft);
@@ -5946,6 +5975,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
opn = "msub.ps";
break;
case OPC_NMADD_S:
+ check_cop1x(ctx);
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WT1, ft);
GEN_LOAD_FREG_FTN(WT2, fr);
@@ -5954,6 +5984,8 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
opn = "nmadd.s";
break;
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(DT1, ft);
GEN_LOAD_FREG_FTN(DT2, fr);
@@ -5962,6 +5994,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
opn = "nmadd.d";
break;
case OPC_NMADD_PS:
+ check_cp1_64bitmode(ctx);
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs);
GEN_LOAD_FREG_FTN(WT1, ft);
@@ -5974,6 +6007,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
opn = "nmadd.ps";
break;
case OPC_NMSUB_S:
+ check_cop1x(ctx);
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WT1, ft);
GEN_LOAD_FREG_FTN(WT2, fr);
@@ -5982,6 +6016,8 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
opn = "nmsub.s";
break;
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(DT1, ft);
GEN_LOAD_FREG_FTN(DT2, fr);
@@ -5990,6 +6026,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t opc,
opn = "nmsub.d";
break;
case OPC_NMSUB_PS:
+ check_cp1_64bitmode(ctx);
GEN_LOAD_FREG_FTN(WT0, fs);
GEN_LOAD_FREG_FTN(WTH0, fs);
GEN_LOAD_FREG_FTN(WT1, ft);
@@ -6465,6 +6502,7 @@ static void decode_opc (CPUState *env, DisasContext *ctx)
#endif
case OPC_BC1ANY2:
case OPC_BC1ANY4:
+ check_cop1x(ctx);
check_insn(env, ctx, ASE_MIPS3D);
/* fall through */
case OPC_BC1: