MIPS: Add MAC2008 Support
MAC2008 means the processor implemented IEEE754 style Fused MADD instruction. It was introduced in Release3 but removed in Release5. The toolchain support of MAC2008 have never landed except for Loongson processors. This patch aimed to disabled the MAC2008 if it's optional. For MAC2008 only processors, we corrected math-emu behavior to align with actual hardware behavior. Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com> [paulburton@kernel.org: Fixup MIPSr2-r5 check in cpu_set_fpu_2008.] Signed-off-by: Paul Burton <paulburton@kernel.org> Cc: linux-mips@vger.kernel.org Cc: chenhc@lemote.com Cc: paul.burton@mips.com Cc: linux-kernel@vger.kernel.org
This commit is contained in:
@@ -1514,16 +1514,28 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
|
||||
break;
|
||||
|
||||
case madd_s_op:
|
||||
handler = fpemu_sp_madd;
|
||||
if (cpu_has_mac2008_only)
|
||||
handler = ieee754sp_madd;
|
||||
else
|
||||
handler = fpemu_sp_madd;
|
||||
goto scoptop;
|
||||
case msub_s_op:
|
||||
handler = fpemu_sp_msub;
|
||||
if (cpu_has_mac2008_only)
|
||||
handler = ieee754sp_msub;
|
||||
else
|
||||
handler = fpemu_sp_msub;
|
||||
goto scoptop;
|
||||
case nmadd_s_op:
|
||||
handler = fpemu_sp_nmadd;
|
||||
if (cpu_has_mac2008_only)
|
||||
handler = ieee754sp_nmadd;
|
||||
else
|
||||
handler = fpemu_sp_nmadd;
|
||||
goto scoptop;
|
||||
case nmsub_s_op:
|
||||
handler = fpemu_sp_nmsub;
|
||||
if (cpu_has_mac2008_only)
|
||||
handler = ieee754sp_nmsub;
|
||||
else
|
||||
handler = fpemu_sp_nmsub;
|
||||
goto scoptop;
|
||||
|
||||
scoptop:
|
||||
@@ -1610,15 +1622,27 @@ static int fpux_emu(struct pt_regs *xcp, struct mips_fpu_struct *ctx,
|
||||
break;
|
||||
|
||||
case madd_d_op:
|
||||
handler = fpemu_dp_madd;
|
||||
if (cpu_has_mac2008_only)
|
||||
handler = ieee754dp_madd;
|
||||
else
|
||||
handler = fpemu_dp_madd;
|
||||
goto dcoptop;
|
||||
case msub_d_op:
|
||||
handler = fpemu_dp_msub;
|
||||
if (cpu_has_mac2008_only)
|
||||
handler = ieee754dp_msub;
|
||||
else
|
||||
handler = fpemu_dp_msub;
|
||||
goto dcoptop;
|
||||
case nmadd_d_op:
|
||||
handler = fpemu_dp_nmadd;
|
||||
if (cpu_has_mac2008_only)
|
||||
handler = ieee754dp_nmadd;
|
||||
else
|
||||
handler = fpemu_dp_nmadd;
|
||||
goto dcoptop;
|
||||
case nmsub_d_op:
|
||||
if (cpu_has_mac2008_only)
|
||||
handler = ieee754dp_nmsub;
|
||||
else
|
||||
handler = fpemu_dp_nmsub;
|
||||
goto dcoptop;
|
||||
|
||||
|
@@ -68,6 +68,12 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
|
||||
|
||||
ieee754_clearcx();
|
||||
|
||||
rs = xs ^ ys;
|
||||
if (flags & MADDF_NEGATE_PRODUCT)
|
||||
rs ^= 1;
|
||||
if (flags & MADDF_NEGATE_ADDITION)
|
||||
zs ^= 1;
|
||||
|
||||
/*
|
||||
* Handle the cases when at least one of x, y or z is a NaN.
|
||||
* Order of precedence is sNaN, qNaN and z, x, y.
|
||||
@@ -104,9 +110,7 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
|
||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
|
||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
|
||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
|
||||
if ((zc == IEEE754_CLASS_INF) &&
|
||||
((!(flags & MADDF_NEGATE_PRODUCT) && (zs != (xs ^ ys))) ||
|
||||
((flags & MADDF_NEGATE_PRODUCT) && (zs == (xs ^ ys))))) {
|
||||
if ((zc == IEEE754_CLASS_INF) && (zs != rs)) {
|
||||
/*
|
||||
* Cases of addition of infinities with opposite signs
|
||||
* or subtraction of infinities with same signs.
|
||||
@@ -116,15 +120,10 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
|
||||
}
|
||||
/*
|
||||
* z is here either not an infinity, or an infinity having the
|
||||
* same sign as product (x*y) (in case of MADDF.D instruction)
|
||||
* or product -(x*y) (in MSUBF.D case). The result must be an
|
||||
* infinity, and its sign is determined only by the value of
|
||||
* (flags & MADDF_NEGATE_PRODUCT) and the signs of x and y.
|
||||
* same sign as product (x*y). The result must be an infinity,
|
||||
* and its sign is determined only by the sign of product (x*y).
|
||||
*/
|
||||
if (flags & MADDF_NEGATE_PRODUCT)
|
||||
return ieee754dp_inf(1 ^ (xs ^ ys));
|
||||
else
|
||||
return ieee754dp_inf(xs ^ ys);
|
||||
return ieee754dp_inf(rs);
|
||||
|
||||
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
|
||||
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
|
||||
@@ -135,10 +134,7 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
|
||||
return ieee754dp_inf(zs);
|
||||
if (zc == IEEE754_CLASS_ZERO) {
|
||||
/* Handle cases +0 + (-0) and similar ones. */
|
||||
if ((!(flags & MADDF_NEGATE_PRODUCT)
|
||||
&& (zs == (xs ^ ys))) ||
|
||||
((flags & MADDF_NEGATE_PRODUCT)
|
||||
&& (zs != (xs ^ ys))))
|
||||
if (zs == rs)
|
||||
/*
|
||||
* Cases of addition of zeros of equal signs
|
||||
* or subtraction of zeroes of opposite signs.
|
||||
@@ -187,9 +183,6 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x,
|
||||
assert(ym & DP_HIDDEN_BIT);
|
||||
|
||||
re = xe + ye;
|
||||
rs = xs ^ ys;
|
||||
if (flags & MADDF_NEGATE_PRODUCT)
|
||||
rs ^= 1;
|
||||
|
||||
/* shunt to top of word */
|
||||
xm <<= 64 - (DP_FBITS + 1);
|
||||
@@ -340,3 +333,27 @@ union ieee754dp ieee754dp_msubf(union ieee754dp z, union ieee754dp x,
|
||||
{
|
||||
return _dp_maddf(z, x, y, MADDF_NEGATE_PRODUCT);
|
||||
}
|
||||
|
||||
union ieee754dp ieee754dp_madd(union ieee754dp z, union ieee754dp x,
|
||||
union ieee754dp y)
|
||||
{
|
||||
return _dp_maddf(z, x, y, 0);
|
||||
}
|
||||
|
||||
union ieee754dp ieee754dp_msub(union ieee754dp z, union ieee754dp x,
|
||||
union ieee754dp y)
|
||||
{
|
||||
return _dp_maddf(z, x, y, MADDF_NEGATE_ADDITION);
|
||||
}
|
||||
|
||||
union ieee754dp ieee754dp_nmadd(union ieee754dp z, union ieee754dp x,
|
||||
union ieee754dp y)
|
||||
{
|
||||
return _dp_maddf(z, x, y, MADDF_NEGATE_PRODUCT|MADDF_NEGATE_ADDITION);
|
||||
}
|
||||
|
||||
union ieee754dp ieee754dp_nmsub(union ieee754dp z, union ieee754dp x,
|
||||
union ieee754dp y)
|
||||
{
|
||||
return _dp_maddf(z, x, y, MADDF_NEGATE_PRODUCT);
|
||||
}
|
||||
|
@@ -68,6 +68,14 @@ union ieee754sp ieee754sp_maddf(union ieee754sp z, union ieee754sp x,
|
||||
union ieee754sp y);
|
||||
union ieee754sp ieee754sp_msubf(union ieee754sp z, union ieee754sp x,
|
||||
union ieee754sp y);
|
||||
union ieee754sp ieee754sp_madd(union ieee754sp z, union ieee754sp x,
|
||||
union ieee754sp y);
|
||||
union ieee754sp ieee754sp_msub(union ieee754sp z, union ieee754sp x,
|
||||
union ieee754sp y);
|
||||
union ieee754sp ieee754sp_nmadd(union ieee754sp z, union ieee754sp x,
|
||||
union ieee754sp y);
|
||||
union ieee754sp ieee754sp_nmsub(union ieee754sp z, union ieee754sp x,
|
||||
union ieee754sp y);
|
||||
int ieee754sp_2008class(union ieee754sp x);
|
||||
union ieee754sp ieee754sp_fmin(union ieee754sp x, union ieee754sp y);
|
||||
union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y);
|
||||
@@ -103,6 +111,14 @@ union ieee754dp ieee754dp_maddf(union ieee754dp z, union ieee754dp x,
|
||||
union ieee754dp y);
|
||||
union ieee754dp ieee754dp_msubf(union ieee754dp z, union ieee754dp x,
|
||||
union ieee754dp y);
|
||||
union ieee754dp ieee754dp_madd(union ieee754dp z, union ieee754dp x,
|
||||
union ieee754dp y);
|
||||
union ieee754dp ieee754dp_msub(union ieee754dp z, union ieee754dp x,
|
||||
union ieee754dp y);
|
||||
union ieee754dp ieee754dp_nmadd(union ieee754dp z, union ieee754dp x,
|
||||
union ieee754dp y);
|
||||
union ieee754dp ieee754dp_nmsub(union ieee754dp z, union ieee754dp x,
|
||||
union ieee754dp y);
|
||||
int ieee754dp_2008class(union ieee754dp x);
|
||||
union ieee754dp ieee754dp_fmin(union ieee754dp x, union ieee754dp y);
|
||||
union ieee754dp ieee754dp_fmina(union ieee754dp x, union ieee754dp y);
|
||||
|
@@ -16,6 +16,7 @@
|
||||
|
||||
enum maddf_flags {
|
||||
MADDF_NEGATE_PRODUCT = 1 << 0,
|
||||
MADDF_NEGATE_ADDITION = 1 << 1,
|
||||
};
|
||||
|
||||
static inline void ieee754_clearcx(void)
|
||||
|
@@ -36,6 +36,12 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
|
||||
|
||||
ieee754_clearcx();
|
||||
|
||||
rs = xs ^ ys;
|
||||
if (flags & MADDF_NEGATE_PRODUCT)
|
||||
rs ^= 1;
|
||||
if (flags & MADDF_NEGATE_ADDITION)
|
||||
zs ^= 1;
|
||||
|
||||
/*
|
||||
* Handle the cases when at least one of x, y or z is a NaN.
|
||||
* Order of precedence is sNaN, qNaN and z, x, y.
|
||||
@@ -73,9 +79,7 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
|
||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM):
|
||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
|
||||
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF):
|
||||
if ((zc == IEEE754_CLASS_INF) &&
|
||||
((!(flags & MADDF_NEGATE_PRODUCT) && (zs != (xs ^ ys))) ||
|
||||
((flags & MADDF_NEGATE_PRODUCT) && (zs == (xs ^ ys))))) {
|
||||
if ((zc == IEEE754_CLASS_INF) && (zs != rs)) {
|
||||
/*
|
||||
* Cases of addition of infinities with opposite signs
|
||||
* or subtraction of infinities with same signs.
|
||||
@@ -85,15 +89,10 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
|
||||
}
|
||||
/*
|
||||
* z is here either not an infinity, or an infinity having the
|
||||
* same sign as product (x*y) (in case of MADDF.D instruction)
|
||||
* or product -(x*y) (in MSUBF.D case). The result must be an
|
||||
* infinity, and its sign is determined only by the value of
|
||||
* (flags & MADDF_NEGATE_PRODUCT) and the signs of x and y.
|
||||
* same sign as product (x*y). The result must be an infinity,
|
||||
* and its sign is determined only by the sign of product (x*y).
|
||||
*/
|
||||
if (flags & MADDF_NEGATE_PRODUCT)
|
||||
return ieee754sp_inf(1 ^ (xs ^ ys));
|
||||
else
|
||||
return ieee754sp_inf(xs ^ ys);
|
||||
return ieee754sp_inf(rs);
|
||||
|
||||
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
|
||||
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM):
|
||||
@@ -104,10 +103,7 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
|
||||
return ieee754sp_inf(zs);
|
||||
if (zc == IEEE754_CLASS_ZERO) {
|
||||
/* Handle cases +0 + (-0) and similar ones. */
|
||||
if ((!(flags & MADDF_NEGATE_PRODUCT)
|
||||
&& (zs == (xs ^ ys))) ||
|
||||
((flags & MADDF_NEGATE_PRODUCT)
|
||||
&& (zs != (xs ^ ys))))
|
||||
if (zs == rs)
|
||||
/*
|
||||
* Cases of addition of zeros of equal signs
|
||||
* or subtraction of zeroes of opposite signs.
|
||||
@@ -158,9 +154,6 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
|
||||
assert(ym & SP_HIDDEN_BIT);
|
||||
|
||||
re = xe + ye;
|
||||
rs = xs ^ ys;
|
||||
if (flags & MADDF_NEGATE_PRODUCT)
|
||||
rs ^= 1;
|
||||
|
||||
/* Multiple 24 bit xm and ym to give 48 bit results */
|
||||
rm64 = (uint64_t)xm * ym;
|
||||
@@ -260,3 +253,27 @@ union ieee754sp ieee754sp_msubf(union ieee754sp z, union ieee754sp x,
|
||||
{
|
||||
return _sp_maddf(z, x, y, MADDF_NEGATE_PRODUCT);
|
||||
}
|
||||
|
||||
union ieee754sp ieee754sp_madd(union ieee754sp z, union ieee754sp x,
|
||||
union ieee754sp y)
|
||||
{
|
||||
return _sp_maddf(z, x, y, 0);
|
||||
}
|
||||
|
||||
union ieee754sp ieee754sp_msub(union ieee754sp z, union ieee754sp x,
|
||||
union ieee754sp y)
|
||||
{
|
||||
return _sp_maddf(z, x, y, MADDF_NEGATE_ADDITION);
|
||||
}
|
||||
|
||||
union ieee754sp ieee754sp_nmadd(union ieee754sp z, union ieee754sp x,
|
||||
union ieee754sp y)
|
||||
{
|
||||
return _sp_maddf(z, x, y, MADDF_NEGATE_PRODUCT|MADDF_NEGATE_ADDITION);
|
||||
}
|
||||
|
||||
union ieee754sp ieee754sp_nmsub(union ieee754sp z, union ieee754sp x,
|
||||
union ieee754sp y)
|
||||
{
|
||||
return _sp_maddf(z, x, y, MADDF_NEGATE_PRODUCT);
|
||||
}
|
||||
|
Reference in New Issue
Block a user