diff options
author | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-12-30 15:36:58 +0000 |
---|---|---|
committer | ths <ths@c046a42c-6fe2-441c-8c8c-71466251a162> | 2007-12-30 15:36:58 +0000 |
commit | b8aa4598e2cc109b0884740a42116acaab01e67d (patch) | |
tree | 841da3e790c3a04b10dc4a4e96370c1128f8f2dc /target-mips/translate.c | |
parent | 6341fdcb7841f364a6102ce2b3c375e6c0d7560e (diff) | |
download | qemu-b8aa4598e2cc109b0884740a42116acaab01e67d.zip |
MIPS COP1X (and related) instructions, by Richard Sandiford.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3877 c046a42c-6fe2-441c-8c8c-71466251a162
Diffstat (limited to 'target-mips/translate.c')
-rw-r--r-- | target-mips/translate.c | 56 |
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: |