qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH v2 16/22] target-mips: add new Floating Point in


From: Aurelien Jarno
Subject: Re: [Qemu-devel] [PATCH v2 16/22] target-mips: add new Floating Point instructions
Date: Fri, 20 Jun 2014 23:14:19 +0200
User-agent: Mutt/1.5.21 (2010-09-15)

On Wed, Jun 11, 2014 at 04:19:46PM +0100, Leon Alrae wrote:
> 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.

I don't think we can "update" softfloat. The existing version has to
stay to correctly emulate the existing CPU, and unfortunately things like
the sNaN bit is not even configurable at runtime, but fixed at compile time
(in softfloat-specialize.h). How do you plan to handle that?

> Signed-off-by: Leon Alrae <address@hidden>
> ---
>  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)
> +

Why not using FOP_PROTO here?

> +#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
> +

But using it here.

Also I guess you can reuse the existing FOP_PROTO macros.

>  #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
> 
> 

-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
address@hidden                 http://www.aurel32.net



reply via email to

[Prev in Thread] Current Thread [Next in Thread]