Commit 0c64fe63 authored by Aleksandar Markovic's avatar Aleksandar Markovic Committed by Ralf Baechle

MIPS: math-emu: <MADDF|MSUBF>.<D|S>: Fix some cases of infinite inputs

Fix the cases of <MADDF|MSUBF>.<D|S> when any of two multiplicands is
infinity. The correct behavior in such cases is affected by the nature
of third input. Cases of addition of infinities with opposite signs
and subtraction of infinities with same signs may arise and must be
handles separately. Also, the value od flags argument (that determines
whether the instruction is MADDF or MSUBF) affects the outcome.

Relevant examples:

MADDF.S fd,fs,ft:
  If fs contains +inf, ft contains +inf, and fd contains -inf, fd is
  going to contain indef (without this patch, it used to contain
  -inf).

MSUBF.S fd,fs,ft:
  If fs contains +inf, ft contains 1.0, and fd contains +0.0, fd is
  going to contain -inf (without this patch, it used to contain +inf).

Fixes: e24c3bec ("MIPS: math-emu: Add support for the MIPS R6 MADDF FPU instruction")
Fixes: 83d43305 ("MIPS: math-emu: Add support for the MIPS R6 MSUBF FPU instruction")
Signed-off-by: default avatarDouglas Leung <douglas.leung@imgtec.com>
Signed-off-by: default avatarMiodrag Dinic <miodrag.dinic@imgtec.com>
Signed-off-by: default avatarGoran Ferenc <goran.ferenc@imgtec.com>
Signed-off-by: default avatarAleksandar Markovic <aleksandar.markovic@imgtec.com>
Reviewed-by: default avatarJames Hogan <james.hogan@imgtec.com>
Cc: Douglas Leung <douglas.leung@imgtec.com>
Cc: Bo Hu <bohu@google.com>
Cc: Jin Qian <jinqian@google.com>
Cc: Paul Burton <paul.burton@imgtec.com>
Cc: Petar Jovanovic <petar.jovanovic@imgtec.com>
Cc: Raghu Gandham <raghu.gandham@imgtec.com>
Cc: <stable@vger.kernel.org> # 4.7+
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/16887/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent e840be6e
...@@ -84,6 +84,26 @@ static union ieee754dp _dp_maddf(union ieee754dp z, union ieee754dp x, ...@@ -84,6 +84,26 @@ 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_NORM):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): 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))))) {
/*
* Cases of addition of infinities with opposite signs
* or subtraction of infinities with same signs.
*/
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754dp_indef();
}
/*
* 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.
*/
if (flags & maddf_negate_product)
return ieee754dp_inf(1 ^ (xs ^ ys));
else
return ieee754dp_inf(xs ^ ys); return ieee754dp_inf(xs ^ ys);
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
......
...@@ -85,6 +85,26 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x, ...@@ -85,6 +85,26 @@ 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_NORM):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM):
case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): 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))))) {
/*
* Cases of addition of infinities with opposite signs
* or subtraction of infinities with same signs.
*/
ieee754_setcx(IEEE754_INVALID_OPERATION);
return ieee754sp_indef();
}
/*
* 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.
*/
if (flags & maddf_negate_product)
return ieee754sp_inf(1 ^ (xs ^ ys));
else
return ieee754sp_inf(xs ^ ys); return ieee754sp_inf(xs ^ ys);
case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO):
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment