mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
target-mips: add new Floating Point instructions
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>
This commit is contained in:
@@ -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},
|
||||
|
||||
@@ -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) \
|
||||
@@ -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) \
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
+423
-70
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user