64-bit paired-single (PS) floating point data type is optional in the
pre-Release 6.
It has to raise RI exception when PS type is not implemented. (FIR.PS = 0)
(The PS data type is removed in the Release 6.)
Loongson-2E and Loongson-2F don't have any implementation field in FCSR0(FIR)
but do support PS data format, therefore for these cores RI will not be
signalled regardless of PS bit.

Signed-off-by: Yongbok Kim <yongbok....@imgtec.com>
Reviewed-by: Leon Alrae <leon.al...@imgtec.com>
---
 target-mips/translate.c |   78 +++++++++++++++++++++++++++--------------------
 1 files changed, 45 insertions(+), 33 deletions(-)

diff --git a/target-mips/translate.c b/target-mips/translate.c
index dc9aae6..851a27c 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -1429,6 +1429,7 @@ typedef struct DisasContext {
     uint64_t PAMask;
     bool mvh;
     int CP0_LLAddr_shift;
+    bool ps;
 } DisasContext;
 
 enum {
@@ -1825,6 +1826,16 @@ static inline void check_insn_opc_removed(DisasContext 
*ctx, int flags)
     }
 }
 
+/* This code generates a "reserved instruction" exception if the
+   CPU does not support 64-bit paired-single (PS) floating point data type */
+static inline void check_ps(DisasContext *ctx)
+{
+    if (unlikely(!ctx->ps)) {
+        generate_exception(ctx, EXCP_RI);
+    }
+    check_cp1_64bitmode(ctx);
+}
+
 #ifdef TARGET_MIPS64
 /* This code generates a "reserved instruction" exception if 64-bit
    instructions are not enabled. */
@@ -1858,7 +1869,7 @@ static inline void gen_cmp ## type ## _ ## 
fmt(DisasContext *ctx, int n,      \
     TCGv_i##bits fp1 = tcg_temp_new_i##bits ();                               \
     switch (ifmt) {                                                           \
     case FMT_PS:                                                              \
-        check_cp1_64bitmode(ctx);                                             \
+        check_ps(ctx);                                                        \
         break;                                                                \
     case FMT_D:                                                               \
         if (abs) {                                                            \
@@ -8998,7 +9009,6 @@ static void gen_farith (DisasContext *ctx, enum fopcode 
op1,
     };
     enum { BINOP, CMPOP, OTHEROP } optype = OTHEROP;
     uint32_t func = ctx->opcode & 0x3f;
-
     switch (op1) {
     case OPC_ADD_S:
         {
@@ -9491,8 +9501,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode 
op1,
         opn = "cvt.l.s";
         break;
     case OPC_CVT_PS_S:
-        check_insn_opc_removed(ctx, ISA_MIPS32R6);
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i64 fp64 = tcg_temp_new_i64();
             TCGv_i32 fp32_0 = tcg_temp_new_i32();
@@ -10109,8 +10118,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode 
op1,
         opn = "cvt.d.l";
         break;
     case OPC_CVT_PS_PW:
-        check_insn_opc_removed(ctx, ISA_MIPS32R6);
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
 
@@ -10122,7 +10130,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode 
op1,
         opn = "cvt.ps.pw";
         break;
     case OPC_ADD_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
             TCGv_i64 fp1 = tcg_temp_new_i64();
@@ -10137,7 +10145,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode 
op1,
         opn = "add.ps";
         break;
     case OPC_SUB_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
             TCGv_i64 fp1 = tcg_temp_new_i64();
@@ -10152,7 +10160,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode 
op1,
         opn = "sub.ps";
         break;
     case OPC_MUL_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
             TCGv_i64 fp1 = tcg_temp_new_i64();
@@ -10167,7 +10175,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode 
op1,
         opn = "mul.ps";
         break;
     case OPC_ABS_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
 
@@ -10179,7 +10187,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode 
op1,
         opn = "abs.ps";
         break;
     case OPC_MOV_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
 
@@ -10190,7 +10198,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode 
op1,
         opn = "mov.ps";
         break;
     case OPC_NEG_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
 
@@ -10202,12 +10210,12 @@ static void gen_farith (DisasContext *ctx, enum 
fopcode op1,
         opn = "neg.ps";
         break;
     case OPC_MOVCF_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         gen_movcf_ps(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
         opn = "movcf.ps";
         break;
     case OPC_MOVZ_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGLabel *l1 = gen_new_label();
             TCGv_i64 fp0;
@@ -10223,7 +10231,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode 
op1,
         opn = "movz.ps";
         break;
     case OPC_MOVN_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGLabel *l1 = gen_new_label();
             TCGv_i64 fp0;
@@ -10240,7 +10248,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode 
op1,
         opn = "movn.ps";
         break;
     case OPC_ADDR_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
             TCGv_i64 fp1 = tcg_temp_new_i64();
@@ -10255,7 +10263,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode 
op1,
         opn = "addr.ps";
         break;
     case OPC_MULR_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
             TCGv_i64 fp1 = tcg_temp_new_i64();
@@ -10270,7 +10278,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode 
op1,
         opn = "mulr.ps";
         break;
     case OPC_RECIP2_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
             TCGv_i64 fp1 = tcg_temp_new_i64();
@@ -10285,7 +10293,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode 
op1,
         opn = "recip2.ps";
         break;
     case OPC_RECIP1_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
 
@@ -10297,7 +10305,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode 
op1,
         opn = "recip1.ps";
         break;
     case OPC_RSQRT1_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
 
@@ -10309,7 +10317,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode 
op1,
         opn = "rsqrt1.ps";
         break;
     case OPC_RSQRT2_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
             TCGv_i64 fp1 = tcg_temp_new_i64();
@@ -10336,7 +10344,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode 
op1,
         opn = "cvt.s.pu";
         break;
     case OPC_CVT_PW_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
 
@@ -10360,7 +10368,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode 
op1,
         opn = "cvt.s.pl";
         break;
     case OPC_PLL_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
             TCGv_i32 fp1 = tcg_temp_new_i32();
@@ -10375,7 +10383,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode 
op1,
         opn = "pll.ps";
         break;
     case OPC_PLU_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
             TCGv_i32 fp1 = tcg_temp_new_i32();
@@ -10390,7 +10398,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode 
op1,
         opn = "plu.ps";
         break;
     case OPC_PUL_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
             TCGv_i32 fp1 = tcg_temp_new_i32();
@@ -10405,7 +10413,7 @@ static void gen_farith (DisasContext *ctx, enum fopcode 
op1,
         opn = "pul.ps";
         break;
     case OPC_PUU_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
             TCGv_i32 fp1 = tcg_temp_new_i32();
@@ -10564,7 +10572,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t 
opc,
 
     switch (opc) {
     case OPC_ALNV_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv t0 = tcg_temp_local_new();
             TCGv_i32 fp = tcg_temp_new_i32();
@@ -10639,7 +10647,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t 
opc,
         opn = "madd.d";
         break;
     case OPC_MADD_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
             TCGv_i64 fp1 = tcg_temp_new_i64();
@@ -10694,7 +10702,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t 
opc,
         opn = "msub.d";
         break;
     case OPC_MSUB_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
             TCGv_i64 fp1 = tcg_temp_new_i64();
@@ -10749,7 +10757,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t 
opc,
         opn = "nmadd.d";
         break;
     case OPC_NMADD_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
             TCGv_i64 fp1 = tcg_temp_new_i64();
@@ -10804,7 +10812,7 @@ static void gen_flt3_arith (DisasContext *ctx, uint32_t 
opc,
         opn = "nmsub.d";
         break;
     case OPC_NMSUB_PS:
-        check_cp1_64bitmode(ctx);
+        check_ps(ctx);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
             TCGv_i64 fp1 = tcg_temp_new_i64();
@@ -14108,6 +14116,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, 
DisasContext *ctx)
                         gen_movcf_d(ctx, rs, rt, cc, 0);
                         break;
                     case FMT_SDPS_PS:
+                        check_ps(ctx);
                         gen_movcf_ps(ctx, rs, rt, cc, 0);
                         break;
                     default:
@@ -14123,6 +14132,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, 
DisasContext *ctx)
                         gen_movcf_d(ctx, rs, rt, cc, 1);
                         break;
                     case FMT_SDPS_PS:
+                        check_ps(ctx);
                         gen_movcf_ps(ctx, rs, rt, cc, 1);
                         break;
                     default:
@@ -14144,6 +14154,7 @@ static void decode_micromips32_opc(CPUMIPSState *env, 
DisasContext *ctx)
                     mips32_op = OPC_##prfx##_D;         \
                     goto do_fpop;                       \
                 case FMT_SDPS_PS:                       \
+                    check_ps(ctx);                      \
                     mips32_op = OPC_##prfx##_PS;        \
                     goto do_fpop;                       \
                 default:                                \
@@ -19149,8 +19160,7 @@ static void decode_opc(CPUMIPSState *env, DisasContext 
*ctx)
                                 (rt >> 2) & 0x7, imm << 2);
             break;
         case OPC_PS_FMT:
-            check_cp1_enabled(ctx);
-            check_insn_opc_removed(ctx, ISA_MIPS32R6);
+            check_ps(ctx);
             /* fall through */
         case OPC_S_FMT:
         case OPC_D_FMT:
@@ -19459,6 +19469,8 @@ gen_intermediate_code_internal(MIPSCPU *cpu, 
TranslationBlock *tb,
     /* Restore delay slot state from the tb context.  */
     ctx.hflags = (uint32_t)tb->flags; /* FIXME: maybe use 64 bits here? */
     ctx.ulri = (env->CP0_Config3 >> CP0C3_ULRI) & 1;
+    ctx.ps = ((env->active_fpu.fcr0 >> FCR0_PS) & 1) ||
+             (env->insn_flags & (INSN_LOONGSON2E | INSN_LOONGSON2F));
     restore_cpu_state(env, &ctx);
 #ifdef CONFIG_USER_ONLY
         ctx.mem_idx = MIPS_HFLAG_UM;
-- 
1.7.5.4


Reply via email to