All of lore.kernel.org
 help / color / mirror / Atom feed
From: Leon Alrae <leon.alrae@imgtec.com>
To: qemu-devel@nongnu.org
Cc: yongbok.kim@imgtec.com, cristian.cuna@imgtec.com,
	leon.alrae@imgtec.com, aurelien@aurel32.net, rth@twiddle.net
Subject: [Qemu-devel] [PATCH v2 16/22] target-mips: add new Floating Point instructions
Date: Wed, 11 Jun 2014 16:19:46 +0100	[thread overview]
Message-ID: <1402499992-64851-17-git-send-email-leon.alrae@imgtec.com> (raw)
In-Reply-To: <1402499992-64851-1-git-send-email-leon.alrae@imgtec.com>

In terms of encoding MIPS32R6 MIN.fmt, MAX.fmt, MINA.fmt, MAXA.fmt replaced
MIPS-3D RECIP1, RECIP2, RSQRT1, RSQRT2 instructions.

In R6 all Floating Point instructions are supposed to be IEEE-2008 compliant
i.e. FIR.HAS2008 always 1. However, QEMU softfloat for MIPS has not been
updated yet.

Signed-off-by: Leon Alrae <leon.alrae@imgtec.com>
---
 disas/mips.c            |   22 +++
 target-mips/helper.h    |   21 +++
 target-mips/op_helper.c |  108 +++++++++++
 target-mips/translate.c |  449 ++++++++++++++++++++++++++++++++++++++++++-----
 4 files changed, 552 insertions(+), 48 deletions(-)

diff --git a/disas/mips.c b/disas/mips.c
index e041858..6196d2e 100644
--- a/disas/mips.c
+++ b/disas/mips.c
@@ -1263,6 +1263,28 @@ const struct mips_opcode mips_builtin_opcodes[] =
 {"cache",   "k,o(b)",   0x7c000025, 0xfc00003f, RD_b,                 0, I32R6},
 {"seleqz",  "d,v,t",    0x00000035, 0xfc0007ff, WR_d|RD_s|RD_t,       0, I32R6},
 {"selnez",  "d,v,t",    0x00000037, 0xfc0007ff, WR_d|RD_s|RD_t,       0, I32R6},
+{"maddf.s", "D,S,T",    0x46000018, 0xffe0001f, WR_D|RD_S|RD_T|FP_S,  0, I32R6},
+{"maddf.d", "D,S,T",    0x46200018, 0xffe0001f, WR_D|RD_S|RD_T|FP_D,  0, I32R6},
+{"msubf.s", "D,S,T",    0x46000019, 0xffe0001f, WR_D|RD_S|RD_T|FP_S,  0, I32R6},
+{"msubf.d", "D,S,T",    0x46200019, 0xffe0001f, WR_D|RD_S|RD_T|FP_D,  0, I32R6},
+{"max.s",   "D,S,T",    0x4600001e, 0xffe0001f, WR_D|RD_S|RD_T|FP_S,  0, I32R6},
+{"max.d",   "D,S,T",    0x4620001e, 0xffe0001f, WR_D|RD_S|RD_T|FP_D,  0, I32R6},
+{"maxa.s",  "D,S,T",    0x4600001f, 0xffe0001f, WR_D|RD_S|RD_T|FP_S,  0, I32R6},
+{"maxa.d",  "D,S,T",    0x4620001f, 0xffe0001f, WR_D|RD_S|RD_T|FP_D,  0, I32R6},
+{"rint.s",  "D,S",      0x4600001a, 0xffe0001f, WR_D|RD_S|FP_S,       0, I32R6},
+{"rint.d",  "D,S",      0x4620001a, 0xffe0001f, WR_D|RD_S|FP_D,       0, I32R6},
+{"class.s", "D,S",      0x4600001b, 0xffe0001f, WR_D|RD_S|FP_S,       0, I32R6},
+{"class.d", "D,S",      0x4620001b, 0xffe0001f, WR_D|RD_S|FP_D,       0, I32R6},
+{"min.s",   "D,S,T",    0x4600001c, 0xffe0001f, WR_D|RD_S|RD_T|FP_S,  0, I32R6},
+{"min.d",   "D,S,T",    0x4620001c, 0xffe0001f, WR_D|RD_S|RD_T|FP_D,  0, I32R6},
+{"mina.s",  "D,S,T",    0x4600001d, 0xffe0001f, WR_D|RD_S|RD_T|FP_S,  0, I32R6},
+{"mina.d",  "D,S,T",    0x4620001d, 0xffe0001f, WR_D|RD_S|RD_T|FP_D,  0, I32R6},
+{"sel.s",   "D,S,T",    0x46000010, 0xffe0001f, WR_D|RD_S|RD_T|FP_S,  0, I32R6},
+{"sel.d",   "D,S,T",    0x46200010, 0xffe0001f, WR_D|RD_S|RD_T|FP_D,  0, I32R6},
+{"seleqz.s", "D,S,T",   0x46000014, 0xffe0001f, WR_D|RD_S|RD_T|FP_S,  0, I32R6},
+{"seleqz.d", "D,S,T",   0x46200014, 0xffe0001f, WR_D|RD_S|RD_T|FP_D,  0, I32R6},
+{"selnez.s", "D,S,T",   0x46000017, 0xffe0001f, WR_D|RD_S|RD_T|FP_S,  0, I32R6},
+{"selnez.d", "D,S,T",   0x46200017, 0xffe0001f, WR_D|RD_S|RD_T|FP_D,  0, I32R6},
 {"align",   "d,v,t",    0x7c000220, 0xfc00073f, WR_d|RD_s|RD_t,       0, I32R6},
 {"dalign",  "d,v,t",    0x7c000224, 0xfc00063f, WR_d|RD_s|RD_t,       0, I64R6},
 {"bitswap", "d,w",      0x7c000020, 0xffe007ff, WR_d|RD_t,            0, I32R6},
diff --git a/target-mips/helper.h b/target-mips/helper.h
index 5511dfc..8bb3af7 100644
--- a/target-mips/helper.h
+++ b/target-mips/helper.h
@@ -202,6 +202,27 @@ DEF_HELPER_2(float_cvtw_d, i32, env, i64)
 DEF_HELPER_3(float_addr_ps, i64, env, i64, i64)
 DEF_HELPER_3(float_mulr_ps, i64, env, i64, i64)
 
+DEF_HELPER_1(float_class_s, i32, i32)
+DEF_HELPER_1(float_class_d, i64, i64)
+
+DEF_HELPER_2(float_rint_s, i32, env, i32)
+DEF_HELPER_2(float_rint_d, i64, env, i64)
+
+DEF_HELPER_4(float_maddf_s, i32, env, i32, i32, i32)
+DEF_HELPER_4(float_maddf_d, i64, env, i64, i64, i64)
+
+DEF_HELPER_4(float_msubf_s, i32, env, i32, i32, i32)
+DEF_HELPER_4(float_msubf_d, i64, env, i64, i64, i64)
+
+#define FOP_PROTO(op)                                       \
+DEF_HELPER_3(float_ ## op ## _s, i32, env, i32, i32)        \
+DEF_HELPER_3(float_ ## op ## _d, i64, env, i64, i64)
+FOP_PROTO(max)
+FOP_PROTO(maxa)
+FOP_PROTO(min)
+FOP_PROTO(mina)
+#undef FOP_PROTO
+
 #define FOP_PROTO(op)                            \
 DEF_HELPER_2(float_ ## op ## l_s, i64, env, i32) \
 DEF_HELPER_2(float_ ## op ## l_d, i64, env, i64) \
diff --git a/target-mips/op_helper.c b/target-mips/op_helper.c
index 34e9823..fd2cfb9 100644
--- a/target-mips/op_helper.c
+++ b/target-mips/op_helper.c
@@ -2787,6 +2787,114 @@ FLOAT_UNOP(abs)
 FLOAT_UNOP(chs)
 #undef FLOAT_UNOP
 
+#define FLOAT_FMADDSUB(name, bits, muladd_arg)                          \
+uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env,            \
+                                          uint ## bits ## _t fs,        \
+                                          uint ## bits ## _t ft,        \
+                                          uint ## bits ## _t fd)        \
+{                                                                       \
+    uint ## bits ## _t fdret;                                           \
+                                                                        \
+    fdret = float ## bits ## _muladd(fs, ft, fd, muladd_arg,            \
+                                     &env->active_fpu.fp_status);       \
+    update_fcr31(env, GETPC());                                         \
+    return fdret;                                                       \
+}
+
+FLOAT_FMADDSUB(maddf_s, 32, 0)
+FLOAT_FMADDSUB(maddf_d, 64, 0)
+FLOAT_FMADDSUB(msubf_s, 32, float_muladd_negate_product)
+FLOAT_FMADDSUB(msubf_d, 64, float_muladd_negate_product)
+#undef FLOAT_FMADDSUB
+
+#define FLOAT_MINMAX(name, bits, minmaxfunc)                            \
+uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env,            \
+                                          uint ## bits ## _t fs,        \
+                                          uint ## bits ## _t ft)        \
+{                                                                       \
+    uint ## bits ## _t fdret;                                           \
+                                                                        \
+    fdret = float ## bits ## _ ## minmaxfunc (fs, ft,                   \
+                                           &env->active_fpu.fp_status); \
+    update_fcr31(env, GETPC());                                         \
+    return fdret;                                                       \
+}
+
+FLOAT_MINMAX(max_s, 32, maxnum)
+FLOAT_MINMAX(max_d, 64, maxnum)
+FLOAT_MINMAX(maxa_s, 32, maxnummag)
+FLOAT_MINMAX(maxa_d, 64, maxnummag)
+
+FLOAT_MINMAX(min_s, 32, minnum)
+FLOAT_MINMAX(min_d, 64, minnum)
+FLOAT_MINMAX(mina_s, 32, minnummag)
+FLOAT_MINMAX(mina_d, 64, minnummag)
+#undef FLOAT_MINMAX
+
+#define FLOAT_CLASS_SIGNALING_NAN      0x001
+#define FLOAT_CLASS_QUIET_NAN          0x002
+#define FLOAT_CLASS_NEGATIVE_INFINITY  0x004
+#define FLOAT_CLASS_NEGATIVE_NORMAL    0x008
+#define FLOAT_CLASS_NEGATIVE_SUBNORMAL 0x010
+#define FLOAT_CLASS_NEGATIVE_ZERO      0x020
+#define FLOAT_CLASS_POSITIVE_INFINITY  0x040
+#define FLOAT_CLASS_POSITIVE_NORMAL    0x080
+#define FLOAT_CLASS_POSITIVE_SUBNORMAL 0x100
+#define FLOAT_CLASS_POSITIVE_ZERO      0x200
+
+#define FLOAT_CLASS(name, bits)                                      \
+uint ## bits ## _t helper_float_ ## name (uint ## bits ## _t arg)    \
+{                                                                    \
+    if (float ## bits ## _is_signaling_nan(arg)) {                   \
+        return FLOAT_CLASS_SIGNALING_NAN;                            \
+    } else if (float ## bits ## _is_quiet_nan(arg)) {                \
+        return FLOAT_CLASS_QUIET_NAN;                                \
+    } else if (float ## bits ## _is_neg(arg)) {                      \
+        if (float ## bits ## _is_infinity(arg)) {                    \
+            return FLOAT_CLASS_NEGATIVE_INFINITY;                    \
+        } else if (float ## bits ## _is_zero(arg)) {                 \
+            return FLOAT_CLASS_NEGATIVE_ZERO;                        \
+        } else if (float ## bits ## _is_zero_or_denormal(arg)) {     \
+            return FLOAT_CLASS_NEGATIVE_SUBNORMAL;                   \
+        } else {                                                     \
+            return FLOAT_CLASS_NEGATIVE_NORMAL;                      \
+        }                                                            \
+    } else {                                                         \
+        if (float ## bits ## _is_infinity(arg)) {                    \
+            return FLOAT_CLASS_POSITIVE_INFINITY;                    \
+        } else if (float ## bits ## _is_zero(arg)) {                 \
+            return FLOAT_CLASS_POSITIVE_ZERO;                        \
+        } else if (float ## bits ## _is_zero_or_denormal(arg)) {     \
+            return FLOAT_CLASS_POSITIVE_SUBNORMAL;                   \
+        } else {                                                     \
+            return FLOAT_CLASS_POSITIVE_NORMAL;                      \
+        }                                                            \
+    }                                                                \
+}
+
+FLOAT_CLASS(class_s, 32)
+FLOAT_CLASS(class_d, 64)
+#undef FLOAT_CLASS
+
+uint32_t helper_float_rint_s(CPUMIPSState *env, uint32_t fs)
+{
+    uint32_t fd;
+
+    fd = float32_round_to_int(fs, &env->active_fpu.fp_status);
+    update_fcr31(env, GETPC());
+    return fd;
+}
+
+uint64_t helper_float_rint_d(CPUMIPSState *env, uint64_t fs)
+{
+    uint64_t fd;
+
+    fd = float64_round_to_int(fs, &env->active_fpu.fp_status);
+    update_fcr31(env, GETPC());
+    return fd;
+}
+
+
 /* MIPS specific unary operations */
 uint64_t helper_float_recip_d(CPUMIPSState *env, uint64_t fdt0)
 {
diff --git a/target-mips/translate.c b/target-mips/translate.c
index a3cbe48..a686b4a 100644
--- a/target-mips/translate.c
+++ b/target-mips/translate.c
@@ -7601,14 +7601,25 @@ enum fopcode {
     OPC_TRUNC_W_S = FOP(13, FMT_S),
     OPC_CEIL_W_S = FOP(14, FMT_S),
     OPC_FLOOR_W_S = FOP(15, FMT_S),
+    OPC_SEL_S = FOP(16, FMT_S),
     OPC_MOVCF_S = FOP(17, FMT_S),
     OPC_MOVZ_S = FOP(18, FMT_S),
     OPC_MOVN_S = FOP(19, FMT_S),
+    OPC_SELEQZ_S = FOP(20, FMT_S),
     OPC_RECIP_S = FOP(21, FMT_S),
     OPC_RSQRT_S = FOP(22, FMT_S),
+    OPC_SELNEZ_S = FOP(23, FMT_S),
+    OPC_MADDF_S = FOP(24, FMT_S),
+    OPC_MSUBF_S = FOP(25, FMT_S),
+    OPC_RINT_S = FOP(26, FMT_S),
+    OPC_CLASS_S = FOP(27, FMT_S),
+    OPC_MIN_S = FOP(28, FMT_S),
     OPC_RECIP2_S = FOP(28, FMT_S),
+    OPC_MINA_S = FOP(29, FMT_S),
     OPC_RECIP1_S = FOP(29, FMT_S),
+    OPC_MAX_S = FOP(30, FMT_S),
     OPC_RSQRT1_S = FOP(30, FMT_S),
+    OPC_MAXA_S = FOP(31, FMT_S),
     OPC_RSQRT2_S = FOP(31, FMT_S),
     OPC_CVT_D_S = FOP(33, FMT_S),
     OPC_CVT_W_S = FOP(36, FMT_S),
@@ -7647,14 +7658,25 @@ enum fopcode {
     OPC_TRUNC_W_D = FOP(13, FMT_D),
     OPC_CEIL_W_D = FOP(14, FMT_D),
     OPC_FLOOR_W_D = FOP(15, FMT_D),
+    OPC_SEL_D = FOP(16, FMT_D),
     OPC_MOVCF_D = FOP(17, FMT_D),
     OPC_MOVZ_D = FOP(18, FMT_D),
     OPC_MOVN_D = FOP(19, FMT_D),
+    OPC_SELEQZ_D = FOP(20, FMT_D),
     OPC_RECIP_D = FOP(21, FMT_D),
     OPC_RSQRT_D = FOP(22, FMT_D),
+    OPC_SELNEZ_D = FOP(23, FMT_D),
+    OPC_MADDF_D = FOP(24, FMT_D),
+    OPC_MSUBF_D = FOP(25, FMT_D),
+    OPC_RINT_D = FOP(26, FMT_D),
+    OPC_CLASS_D = FOP(27, FMT_D),
+    OPC_MIN_D = FOP(28, FMT_D),
     OPC_RECIP2_D = FOP(28, FMT_D),
+    OPC_MINA_D = FOP(29, FMT_D),
     OPC_RECIP1_D = FOP(29, FMT_D),
+    OPC_MAX_D = FOP(30, FMT_D),
     OPC_RSQRT1_D = FOP(30, FMT_D),
+    OPC_MAXA_D = FOP(31, FMT_D),
     OPC_RSQRT2_D = FOP(31, FMT_D),
     OPC_CVT_S_D = FOP(32, FMT_D),
     OPC_CVT_W_D = FOP(36, FMT_D),
@@ -7910,6 +7932,79 @@ static inline void gen_movcf_ps(DisasContext *ctx, int fs, int fd,
     gen_set_label(l2);
 }
 
+static void gen_sel_s (DisasContext *ctx, enum fopcode op1, int fd, int ft,
+                       int fs)
+{
+    TCGv_i32 t1 = tcg_const_i32(0);
+    TCGv_i32 fp0 = tcg_temp_new_i32();
+    TCGv_i32 fp1 = tcg_temp_new_i32();
+    TCGv_i32 fp2 = tcg_temp_new_i32();
+    gen_load_fpr32(fp0, fd);
+    gen_load_fpr32(fp1, ft);
+    gen_load_fpr32(fp2, fs);
+
+    switch (op1) {
+    case OPC_SEL_S:
+        tcg_gen_andi_i32(fp0, fp0, 1);
+        tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
+        break;
+    case OPC_SELEQZ_S:
+        tcg_gen_andi_i32(fp1, fp1, 1);
+        tcg_gen_movcond_i32(TCG_COND_EQ, fp0, fp1, t1, fp2, t1);
+        break;
+    case OPC_SELNEZ_S:
+        tcg_gen_andi_i32(fp1, fp1, 1);
+        tcg_gen_movcond_i32(TCG_COND_NE, fp0, fp1, t1, fp2, t1);
+        break;
+    default:
+        MIPS_INVAL("gen_sel_s");
+        generate_exception (ctx, EXCP_RI);
+        return;
+    }
+
+    gen_store_fpr32(fp0, fd);
+    tcg_temp_free_i32(fp2);
+    tcg_temp_free_i32(fp1);
+    tcg_temp_free_i32(fp0);
+    tcg_temp_free_i32(t1);
+}
+
+static void gen_sel_d (DisasContext *ctx, enum fopcode op1, int fd, int ft,
+                       int fs)
+{
+    TCGv_i64 t1 = tcg_const_i64(0);
+    TCGv_i64 fp0 = tcg_temp_new_i64();
+    TCGv_i64 fp1 = tcg_temp_new_i64();
+    TCGv_i64 fp2 = tcg_temp_new_i64();
+    gen_load_fpr64(ctx, fp0, fd);
+    gen_load_fpr64(ctx, fp1, ft);
+    gen_load_fpr64(ctx, fp2, fs);
+
+    switch (op1) {
+    case OPC_SEL_D:
+        tcg_gen_andi_i64(fp0, fp0, 1);
+        tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp0, t1, fp1, fp2);
+        break;
+    case OPC_SELEQZ_D:
+        tcg_gen_andi_i64(fp1, fp1, 1);
+        tcg_gen_movcond_i64(TCG_COND_NE, fp0, fp1, t1, t1, fp2);
+        break;
+    case OPC_SELNEZ_D:
+        tcg_gen_andi_i64(fp1, fp1, 1);
+        tcg_gen_movcond_i64(TCG_COND_EQ, fp0, fp1, t1, t1, fp2);
+        break;
+    default:
+        MIPS_INVAL("gen_sel_d");
+        generate_exception (ctx, EXCP_RI);
+        return;
+    }
+
+    gen_store_fpr64(ctx, fp0, fd);
+    tcg_temp_free_i64(fp2);
+    tcg_temp_free_i64(fp1);
+    tcg_temp_free_i64(fp0);
+    tcg_temp_free_i64(t1);
+}
 
 static void gen_farith (DisasContext *ctx, enum fopcode op1,
                         int ft, int fs, int fd, int cc)
@@ -8158,6 +8253,21 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
         }
         opn = "floor.w.s";
         break;
+    case OPC_SEL_S:
+        check_insn(ctx, ISA_MIPS32R6);
+        gen_sel_s(ctx, op1, fd, ft, fs);
+        opn = "sel.s";
+        break;
+    case OPC_SELEQZ_S:
+        check_insn(ctx, ISA_MIPS32R6);
+        gen_sel_s(ctx, op1, fd, ft, fs);
+        opn = "seleqz.s";
+        break;
+    case OPC_SELNEZ_S:
+        check_insn(ctx, ISA_MIPS32R6);
+        gen_sel_s(ctx, op1, fd, ft, fs);
+        opn = "selnez.s";
+        break;
     case OPC_MOVCF_S:
         check_insn_opc_removed(ctx, ISA_MIPS32R6);
         gen_movcf_s(fs, fd, (ft >> 2) & 0x7, ft & 0x1);
@@ -8221,59 +8331,175 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
         }
         opn = "rsqrt.s";
         break;
-    case OPC_RECIP2_S:
-        check_cp1_64bitmode(ctx);
+    case OPC_MADDF_S:
+        check_insn(ctx, ISA_MIPS32R6);
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
             TCGv_i32 fp1 = tcg_temp_new_i32();
-
+            TCGv_i32 fp2 = tcg_temp_new_i32();
             gen_load_fpr32(fp0, fs);
             gen_load_fpr32(fp1, ft);
-            gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
+            gen_load_fpr32(fp2, fd);
+            gen_helper_float_maddf_s(fp2, cpu_env, fp0, fp1, fp2);
+            gen_store_fpr32(fp2, fd);
+            tcg_temp_free_i32(fp2);
             tcg_temp_free_i32(fp1);
-            gen_store_fpr32(fp0, fd);
             tcg_temp_free_i32(fp0);
+            opn = "maddf.s";
         }
-        opn = "recip2.s";
-        break;
-    case OPC_RECIP1_S:
-        check_cp1_64bitmode(ctx);
+    break;
+    case OPC_MSUBF_S:
+        check_insn(ctx, ISA_MIPS32R6);
+        {
+            TCGv_i32 fp0 = tcg_temp_new_i32();
+            TCGv_i32 fp1 = tcg_temp_new_i32();
+            TCGv_i32 fp2 = tcg_temp_new_i32();
+            gen_load_fpr32(fp0, fs);
+            gen_load_fpr32(fp1, ft);
+            gen_load_fpr32(fp2, fd);
+            gen_helper_float_msubf_s(fp2, cpu_env, fp0, fp1, fp2);
+            gen_store_fpr32(fp2, fd);
+            tcg_temp_free_i32(fp2);
+            tcg_temp_free_i32(fp1);
+            tcg_temp_free_i32(fp0);
+            opn = "msubf.s";
+        }
+    break;
+    case OPC_RINT_S:
+        check_insn(ctx, ISA_MIPS32R6);
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
-
             gen_load_fpr32(fp0, fs);
-            gen_helper_float_recip1_s(fp0, cpu_env, fp0);
+            gen_helper_float_rint_s(fp0, cpu_env, fp0);
             gen_store_fpr32(fp0, fd);
             tcg_temp_free_i32(fp0);
+            opn = "rint.s";
         }
-        opn = "recip1.s";
-        break;
-    case OPC_RSQRT1_S:
-        check_cp1_64bitmode(ctx);
+    break;
+    case OPC_CLASS_S:
+        check_insn(ctx, ISA_MIPS32R6);
         {
             TCGv_i32 fp0 = tcg_temp_new_i32();
-
             gen_load_fpr32(fp0, fs);
-            gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
+            gen_helper_float_class_s(fp0, fp0);
             gen_store_fpr32(fp0, fd);
             tcg_temp_free_i32(fp0);
+            opn = "class.s";
+        }
+    break;
+    case OPC_MIN_S: /* OPC_RECIP2_S */
+        if (ctx->insn_flags & ISA_MIPS32R6) {
+            /* OPC_MIN_S */
+            TCGv_i32 fp0 = tcg_temp_new_i32();
+            TCGv_i32 fp1 = tcg_temp_new_i32();
+            TCGv_i32 fp2 = tcg_temp_new_i32();
+            gen_load_fpr32(fp0, fs);
+            gen_load_fpr32(fp1, ft);
+            gen_helper_float_min_s(fp2, cpu_env, fp0, fp1);
+            gen_store_fpr32(fp2, fd);
+            tcg_temp_free_i32(fp2);
+            tcg_temp_free_i32(fp1);
+            tcg_temp_free_i32(fp0);
+            opn = "min.s";
+        } else {
+            /* OPC_RECIP2_S */
+            check_cp1_64bitmode(ctx);
+            {
+                TCGv_i32 fp0 = tcg_temp_new_i32();
+                TCGv_i32 fp1 = tcg_temp_new_i32();
+
+                gen_load_fpr32(fp0, fs);
+                gen_load_fpr32(fp1, ft);
+                gen_helper_float_recip2_s(fp0, cpu_env, fp0, fp1);
+                tcg_temp_free_i32(fp1);
+                gen_store_fpr32(fp0, fd);
+                tcg_temp_free_i32(fp0);
+            }
+            opn = "recip2.s";
         }
-        opn = "rsqrt1.s";
         break;
-    case OPC_RSQRT2_S:
-        check_cp1_64bitmode(ctx);
-        {
+    case OPC_MINA_S: /* OPC_RECIP1_S */
+        if (ctx->insn_flags & ISA_MIPS32R6) {
+            /* OPC_MINA_S */
             TCGv_i32 fp0 = tcg_temp_new_i32();
             TCGv_i32 fp1 = tcg_temp_new_i32();
+            TCGv_i32 fp2 = tcg_temp_new_i32();
+            gen_load_fpr32(fp0, fs);
+            gen_load_fpr32(fp1, ft);
+            gen_helper_float_mina_s(fp2, cpu_env, fp0, fp1);
+            gen_store_fpr32(fp2, fd);
+            tcg_temp_free_i32(fp2);
+            tcg_temp_free_i32(fp1);
+            tcg_temp_free_i32(fp0);
+            opn = "mina.s";
+        } else {
+            /* OPC_RECIP1_S */
+            check_cp1_64bitmode(ctx);
+            {
+                TCGv_i32 fp0 = tcg_temp_new_i32();
 
+                gen_load_fpr32(fp0, fs);
+                gen_helper_float_recip1_s(fp0, cpu_env, fp0);
+                gen_store_fpr32(fp0, fd);
+                tcg_temp_free_i32(fp0);
+            }
+            opn = "recip1.s";
+        }
+        break;
+    case OPC_MAX_S: /* OPC_RSQRT1_S */
+        if (ctx->insn_flags & ISA_MIPS32R6) {
+            /* OPC_MAX_S */
+            TCGv_i32 fp0 = tcg_temp_new_i32();
+            TCGv_i32 fp1 = tcg_temp_new_i32();
             gen_load_fpr32(fp0, fs);
             gen_load_fpr32(fp1, ft);
-            gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
+            gen_helper_float_max_s(fp1, cpu_env, fp0, fp1);
+            gen_store_fpr32(fp1, fd);
+            tcg_temp_free_i32(fp1);
+            tcg_temp_free_i32(fp0);
+            opn = "max.s";
+        } else {
+            /* OPC_RSQRT1_S */
+            check_cp1_64bitmode(ctx);
+            {
+                TCGv_i32 fp0 = tcg_temp_new_i32();
+
+                gen_load_fpr32(fp0, fs);
+                gen_helper_float_rsqrt1_s(fp0, cpu_env, fp0);
+                gen_store_fpr32(fp0, fd);
+                tcg_temp_free_i32(fp0);
+            }
+            opn = "rsqrt1.s";
+        }
+        break;
+    case OPC_MAXA_S: /* OPC_RSQRT2_S */
+        if (ctx->insn_flags & ISA_MIPS32R6) {
+            /* OPC_MAXA_S */
+            TCGv_i32 fp0 = tcg_temp_new_i32();
+            TCGv_i32 fp1 = tcg_temp_new_i32();
+            gen_load_fpr32(fp0, fs);
+            gen_load_fpr32(fp1, ft);
+            gen_helper_float_maxa_s(fp1, cpu_env, fp0, fp1);
+            gen_store_fpr32(fp1, fd);
             tcg_temp_free_i32(fp1);
-            gen_store_fpr32(fp0, fd);
             tcg_temp_free_i32(fp0);
+            opn = "maxa.s";
+        } else {
+            /* OPC_RSQRT2_S */
+            check_cp1_64bitmode(ctx);
+            {
+                TCGv_i32 fp0 = tcg_temp_new_i32();
+                TCGv_i32 fp1 = tcg_temp_new_i32();
+
+                gen_load_fpr32(fp0, fs);
+                gen_load_fpr32(fp1, ft);
+                gen_helper_float_rsqrt2_s(fp0, cpu_env, fp0, fp1);
+                tcg_temp_free_i32(fp1);
+                gen_store_fpr32(fp0, fd);
+                tcg_temp_free_i32(fp0);
+            }
+            opn = "rsqrt2.s";
         }
-        opn = "rsqrt2.s";
         break;
     case OPC_CVT_D_S:
         check_cp1_registers(ctx, fd);
@@ -8572,6 +8798,21 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
         }
         opn = "floor.w.d";
         break;
+    case OPC_SEL_D:
+        check_insn(ctx, ISA_MIPS32R6);
+        gen_sel_d(ctx, op1, fd, ft, fs);
+        opn = "sel.d";
+        break;
+    case OPC_SELEQZ_D:
+        check_insn(ctx, ISA_MIPS32R6);
+        gen_sel_d(ctx, op1, fd, ft, fs);
+        opn = "seleqz.d";
+        break;
+    case OPC_SELNEZ_D:
+        check_insn(ctx, ISA_MIPS32R6);
+        gen_sel_d(ctx, op1, fd, ft, fs);
+        opn = "selnez.d";
+        break;
     case OPC_MOVCF_D:
         check_insn_opc_removed(ctx, ISA_MIPS32R6);
         gen_movcf_d(ctx, fs, fd, (ft >> 2) & 0x7, ft & 0x1);
@@ -8635,59 +8876,171 @@ static void gen_farith (DisasContext *ctx, enum fopcode op1,
         }
         opn = "rsqrt.d";
         break;
-    case OPC_RECIP2_D:
-        check_cp1_64bitmode(ctx);
+    case OPC_MADDF_D:
+        check_insn(ctx, ISA_MIPS32R6);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
             TCGv_i64 fp1 = tcg_temp_new_i64();
-
+            TCGv_i64 fp2 = tcg_temp_new_i64();
             gen_load_fpr64(ctx, fp0, fs);
             gen_load_fpr64(ctx, fp1, ft);
-            gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
+            gen_load_fpr64(ctx, fp2, fd);
+            gen_helper_float_maddf_d(fp2, cpu_env, fp0, fp1, fp2);
+            gen_store_fpr64(ctx, fp2, fd);
+            tcg_temp_free_i64(fp2);
             tcg_temp_free_i64(fp1);
-            gen_store_fpr64(ctx, fp0, fd);
             tcg_temp_free_i64(fp0);
+            opn = "maddf.d";
         }
-        opn = "recip2.d";
-        break;
-    case OPC_RECIP1_D:
-        check_cp1_64bitmode(ctx);
+    break;
+    case OPC_MSUBF_D:
+        check_insn(ctx, ISA_MIPS32R6);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
-
+            TCGv_i64 fp1 = tcg_temp_new_i64();
+            TCGv_i64 fp2 = tcg_temp_new_i64();
             gen_load_fpr64(ctx, fp0, fs);
-            gen_helper_float_recip1_d(fp0, cpu_env, fp0);
+            gen_load_fpr64(ctx, fp1, ft);
+            gen_load_fpr64(ctx, fp2, fd);
+            gen_helper_float_msubf_d(fp2, cpu_env, fp0, fp1, fp2);
+            gen_store_fpr64(ctx, fp2, fd);
+            tcg_temp_free_i64(fp2);
+            tcg_temp_free_i64(fp1);
+            tcg_temp_free_i64(fp0);
+            opn = "msubf.d";
+        }
+    break;
+    case OPC_RINT_D:
+        check_insn(ctx, ISA_MIPS32R6);
+        {
+            TCGv_i64 fp0 = tcg_temp_new_i64();
+            gen_load_fpr64(ctx, fp0, fs);
+            gen_helper_float_rint_d(fp0, cpu_env, fp0);
             gen_store_fpr64(ctx, fp0, fd);
             tcg_temp_free_i64(fp0);
+            opn = "rint.d";
         }
-        opn = "recip1.d";
-        break;
-    case OPC_RSQRT1_D:
-        check_cp1_64bitmode(ctx);
+    break;
+    case OPC_CLASS_D:
+        check_insn(ctx, ISA_MIPS32R6);
         {
             TCGv_i64 fp0 = tcg_temp_new_i64();
-
             gen_load_fpr64(ctx, fp0, fs);
-            gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
+            gen_helper_float_class_d(fp0, fp0);
             gen_store_fpr64(ctx, fp0, fd);
             tcg_temp_free_i64(fp0);
+            opn = "class.d";
+        }
+    break;
+    case OPC_MIN_D: /* OPC_RECIP2_D */
+        if (ctx->insn_flags & ISA_MIPS32R6) {
+            /* OPC_MIN_D */
+            TCGv_i64 fp0 = tcg_temp_new_i64();
+            TCGv_i64 fp1 = tcg_temp_new_i64();
+            gen_load_fpr64(ctx, fp0, fs);
+            gen_load_fpr64(ctx, fp1, ft);
+            gen_helper_float_min_d(fp1, cpu_env, fp0, fp1);
+            gen_store_fpr64(ctx, fp1, fd);
+            tcg_temp_free_i64(fp1);
+            tcg_temp_free_i64(fp0);
+            opn = "min.d";
+        } else {
+            /* OPC_RECIP2_D */
+            check_cp1_64bitmode(ctx);
+            {
+                TCGv_i64 fp0 = tcg_temp_new_i64();
+                TCGv_i64 fp1 = tcg_temp_new_i64();
+
+                gen_load_fpr64(ctx, fp0, fs);
+                gen_load_fpr64(ctx, fp1, ft);
+                gen_helper_float_recip2_d(fp0, cpu_env, fp0, fp1);
+                tcg_temp_free_i64(fp1);
+                gen_store_fpr64(ctx, fp0, fd);
+                tcg_temp_free_i64(fp0);
+            }
+            opn = "recip2.d";
         }
-        opn = "rsqrt1.d";
         break;
-    case OPC_RSQRT2_D:
-        check_cp1_64bitmode(ctx);
-        {
+    case OPC_MINA_D: /* OPC_RECIP1_D */
+        if (ctx->insn_flags & ISA_MIPS32R6) {
+            /* OPC_MINA_D */
+            TCGv_i64 fp0 = tcg_temp_new_i64();
+            TCGv_i64 fp1 = tcg_temp_new_i64();
+            gen_load_fpr64(ctx, fp0, fs);
+            gen_load_fpr64(ctx, fp1, ft);
+            gen_helper_float_mina_d(fp1, cpu_env, fp0, fp1);
+            gen_store_fpr64(ctx, fp1, fd);
+            tcg_temp_free_i64(fp1);
+            tcg_temp_free_i64(fp0);
+            opn = "mina.d";
+        } else {
+            /* OPC_RECIP1_D */
+            check_cp1_64bitmode(ctx);
+            {
+                TCGv_i64 fp0 = tcg_temp_new_i64();
+
+                gen_load_fpr64(ctx, fp0, fs);
+                gen_helper_float_recip1_d(fp0, cpu_env, fp0);
+                gen_store_fpr64(ctx, fp0, fd);
+                tcg_temp_free_i64(fp0);
+            }
+            opn = "recip1.d";
+        }
+        break;
+    case OPC_MAX_D: /*  OPC_RSQRT1_D */
+        if (ctx->insn_flags & ISA_MIPS32R6) {
+            /* OPC_MAX_D */
             TCGv_i64 fp0 = tcg_temp_new_i64();
             TCGv_i64 fp1 = tcg_temp_new_i64();
+            gen_load_fpr64(ctx, fp0, fs);
+            gen_load_fpr64(ctx, fp1, ft);
+            gen_helper_float_max_d(fp1, cpu_env, fp0, fp1);
+            gen_store_fpr64(ctx, fp1, fd);
+            tcg_temp_free_i64(fp1);
+            tcg_temp_free_i64(fp0);
+            opn = "max.s";
+        } else {
+            /* OPC_RSQRT1_D */
+            check_cp1_64bitmode(ctx);
+            {
+                TCGv_i64 fp0 = tcg_temp_new_i64();
 
+                gen_load_fpr64(ctx, fp0, fs);
+                gen_helper_float_rsqrt1_d(fp0, cpu_env, fp0);
+                gen_store_fpr64(ctx, fp0, fd);
+                tcg_temp_free_i64(fp0);
+            }
+            opn = "rsqrt1.d";
+        }
+        break;
+    case OPC_MAXA_D: /* OPC_RSQRT2_D */
+        if (ctx->insn_flags & ISA_MIPS32R6) {
+            /* OPC_MAXA_D */
+            TCGv_i64 fp0 = tcg_temp_new_i64();
+            TCGv_i64 fp1 = tcg_temp_new_i64();
             gen_load_fpr64(ctx, fp0, fs);
             gen_load_fpr64(ctx, fp1, ft);
-            gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
+            gen_helper_float_maxa_d(fp1, cpu_env, fp0, fp1);
+            gen_store_fpr64(ctx, fp1, fd);
             tcg_temp_free_i64(fp1);
-            gen_store_fpr64(ctx, fp0, fd);
             tcg_temp_free_i64(fp0);
+            opn = "maxa.d";
+        } else {
+            /* OPC_RSQRT2_D */
+            check_cp1_64bitmode(ctx);
+            {
+                TCGv_i64 fp0 = tcg_temp_new_i64();
+                TCGv_i64 fp1 = tcg_temp_new_i64();
+
+                gen_load_fpr64(ctx, fp0, fs);
+                gen_load_fpr64(ctx, fp1, ft);
+                gen_helper_float_rsqrt2_d(fp0, cpu_env, fp0, fp1);
+                tcg_temp_free_i64(fp1);
+                gen_store_fpr64(ctx, fp0, fd);
+                tcg_temp_free_i64(fp0);
+            }
+            opn = "rsqrt2.d";
         }
-        opn = "rsqrt2.d";
         break;
     case OPC_CMP_F_D:
     case OPC_CMP_UN_D:
-- 
1.7.5.4

  parent reply	other threads:[~2014-06-11 15:21 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-06-11 15:19 [Qemu-devel] [PATCH v2 00/22] target-mips: add MIPS64R6 Instruction Set support Leon Alrae
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 01/22] target-mips: define ISA_MIPS64R6 Leon Alrae
2014-06-19 21:06   ` Aurelien Jarno
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 02/22] target-mips: signal RI Exception on instructions removed in R6 Leon Alrae
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 03/22] target-mips: add SELEQZ and SELNEZ instructions Leon Alrae
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 04/22] target-mips: move LL and SC instructions Leon Alrae
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 05/22] target-mips: extract decode_opc_special* from decode_opc Leon Alrae
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 06/22] target-mips: split decode_opc_special* into *_r6 and *_legacy Leon Alrae
2014-06-19 21:06   ` Aurelien Jarno
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 07/22] target-mips: signal RI Exception on DSP and Loongson instructions Leon Alrae
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 08/22] target-mips: move PREF, CACHE, LLD and SCD instructions Leon Alrae
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 09/22] target-mips: redefine Integer Multiply and Divide instructions Leon Alrae
2014-06-19 21:06   ` Aurelien Jarno
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 10/22] target-mips: move CLO, DCLO, CLZ, DCLZ, SDBBP and free special2 in R6 Leon Alrae
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 11/22] target-mips: Status.UX/SX/KX enable 32-bit address wrapping Leon Alrae
2014-06-19 21:06   ` Aurelien Jarno
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 12/22] target-mips: add ALIGN, DALIGN, BITSWAP and DBITSWAP instructions Leon Alrae
2014-06-11 16:39   ` Richard Henderson
2014-06-12  8:35     ` Leon Alrae
2014-06-12 14:34       ` Richard Henderson
2014-06-19 21:06   ` Aurelien Jarno
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 13/22] target-mips: add Compact Branches Leon Alrae
2014-06-11 16:52   ` Richard Henderson
2014-06-24 14:03     ` Leon Alrae
2014-06-19 21:06   ` Aurelien Jarno
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 14/22] target-mips: add Addressing and PC-relative instructions Leon Alrae
2014-06-20 20:50   ` Aurelien Jarno
2014-06-24  9:50     ` Leon Alrae
2014-06-24 10:00       ` Peter Maydell
2014-06-24 14:24         ` Richard Henderson
2014-06-24 14:54           ` Peter Maydell
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 15/22] softfloat: add functions corresponding to IEEE-2008 min/maxNumMag Leon Alrae
2014-06-19 21:27   ` Aurelien Jarno
2014-06-11 15:19 ` Leon Alrae [this message]
2014-06-20 21:14   ` [Qemu-devel] [PATCH v2 16/22] target-mips: add new Floating Point instructions Aurelien Jarno
2014-06-24 12:10     ` Leon Alrae
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 17/22] target-mips: add new Floating Point Comparison instructions Leon Alrae
2014-06-20 21:36   ` Aurelien Jarno
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 18/22] target-mips: do not allow Status.FR=0 mode in 64-bit FPU Leon Alrae
2014-06-19 21:27   ` Aurelien Jarno
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 19/22] target-mips: remove JR, BLTZAL, BGEZAL and add NAL, BAL instructions Leon Alrae
2014-06-19 22:22   ` Aurelien Jarno
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 20/22] mips_malta: update malta's pseudo-bootloader - replace JR with JALR Leon Alrae
2014-06-19 21:27   ` Aurelien Jarno
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 21/22] target-mips: use pointers referring to appropriate decoding function Leon Alrae
2014-06-19 22:18   ` Aurelien Jarno
2014-06-20  4:09     ` Richard Henderson
2014-06-11 15:19 ` [Qemu-devel] [PATCH v2 22/22] target-mips: define a new generic CPU supporting MIPS64R6 Leon Alrae
2014-06-19 22:16   ` Aurelien Jarno
2014-06-24 11:56     ` Leon Alrae

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1402499992-64851-17-git-send-email-leon.alrae@imgtec.com \
    --to=leon.alrae@imgtec.com \
    --cc=aurelien@aurel32.net \
    --cc=cristian.cuna@imgtec.com \
    --cc=qemu-devel@nongnu.org \
    --cc=rth@twiddle.net \
    --cc=yongbok.kim@imgtec.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.