Skip to content

Commit

Permalink
target-mips: add new Floating Point instructions
Browse files Browse the repository at this point in the history
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>
Reviewed-by: Yongbok Kim <yongbok.kim@imgtec.com>
  • Loading branch information
Leon Alrae committed Oct 14, 2014
1 parent 2d31e06 commit e7f16ab
Show file tree
Hide file tree
Showing 4 changed files with 543 additions and 44 deletions.
22 changes: 22 additions & 0 deletions disas/mips.c
Expand Up @@ -1263,6 +1263,28 @@ const struct mips_opcode mips_builtin_opcodes[] =
{"cache", "k,o(b)", 0x7c000025, 0xfc00007f, 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, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6},
{"maddf.d", "D,S,T", 0x46200018, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6},
{"msubf.s", "D,S,T", 0x46000019, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6},
{"msubf.d", "D,S,T", 0x46200019, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6},
{"max.s", "D,S,T", 0x4600001e, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6},
{"max.d", "D,S,T", 0x4620001e, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6},
{"maxa.s", "D,S,T", 0x4600001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6},
{"maxa.d", "D,S,T", 0x4620001f, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6},
{"rint.s", "D,S", 0x4600001a, 0xffff003f, WR_D|RD_S|FP_S, 0, I32R6},
{"rint.d", "D,S", 0x4620001a, 0xffff003f, WR_D|RD_S|FP_D, 0, I32R6},
{"class.s", "D,S", 0x4600001b, 0xffff003f, WR_D|RD_S|FP_S, 0, I32R6},
{"class.d", "D,S", 0x4620001b, 0xffff003f, WR_D|RD_S|FP_D, 0, I32R6},
{"min.s", "D,S,T", 0x4600001c, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6},
{"min.d", "D,S,T", 0x4620001c, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6},
{"mina.s", "D,S,T", 0x4600001d, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6},
{"mina.d", "D,S,T", 0x4620001d, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6},
{"sel.s", "D,S,T", 0x46000010, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6},
{"sel.d", "D,S,T", 0x46200010, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6},
{"seleqz.s", "D,S,T", 0x46000014, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6},
{"seleqz.d", "D,S,T", 0x46200014, 0xffe0003f, WR_D|RD_S|RD_T|FP_D, 0, I32R6},
{"selnez.s", "D,S,T", 0x46000017, 0xffe0003f, WR_D|RD_S|RD_T|FP_S, 0, I32R6},
{"selnez.d", "D,S,T", 0x46200017, 0xffe0003f, 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},
Expand Down
20 changes: 20 additions & 0 deletions target-mips/helper.h
Expand Up @@ -202,6 +202,25 @@ 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_FLAGS_1(float_class_s, TCG_CALL_NO_RWG_SE, i32, i32)
DEF_HELPER_FLAGS_1(float_class_d, TCG_CALL_NO_RWG_SE, i64, i64)

#define FOP_PROTO(op) \
DEF_HELPER_4(float_ ## op ## _s, i32, env, i32, i32, i32) \
DEF_HELPER_4(float_ ## op ## _d, i64, env, i64, i64, i64)
FOP_PROTO(maddf)
FOP_PROTO(msubf)
#undef FOP_PROTO

#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) \
Expand All @@ -219,6 +238,7 @@ DEF_HELPER_2(float_ ## op ## _d, i64, env, i64)
FOP_PROTO(sqrt)
FOP_PROTO(rsqrt)
FOP_PROTO(recip)
FOP_PROTO(rint)
#undef FOP_PROTO

#define FOP_PROTO(op) \
Expand Down
104 changes: 104 additions & 0 deletions target-mips/op_helper.c
Expand Up @@ -2809,6 +2809,110 @@ 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_RINT(name, bits) \
uint ## bits ## _t helper_float_ ## name (CPUMIPSState *env, \
uint ## bits ## _t fs) \
{ \
uint ## bits ## _t fdret; \
\
fdret = float ## bits ## _round_to_int(fs, &env->active_fpu.fp_status); \
update_fcr31(env, GETPC()); \
return fdret; \
}

FLOAT_RINT(rint_s, 32)
FLOAT_RINT(rint_d, 64)
#undef FLOAT_RINT

#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

/* MIPS specific unary operations */
uint64_t helper_float_recip_d(CPUMIPSState *env, uint64_t fdt0)
{
Expand Down

0 comments on commit e7f16ab

Please sign in to comment.