UPSTREAM: MIPS: math-emu: Fix m{add,sub}.s shifts
The code in _sp_maddf (formerly ieee754sp_madd) appears to have been
copied verbatim from ieee754sp_add, and although it's adding the
unpacked "r" & "z" floats it kept using macros that operate on "x" &
"y". This led to the addition being carried out incorrectly on some
mismash of the product, accumulator & multiplicand fields. Typically
this would lead to the assertions "ze == re" & "ze <= SP_EMAX" failing
since ze & re hadn't been operated upon.
Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Fixes: e24c3bec3e
("MIPS: math-emu: Add support for the MIPS R6 MADDF FPU instruction")
Cc: Adam Buchbinder <adam.buchbinder@gmail.com>
Cc: Maciej W. Rozycki <macro@imgtec.com>
Cc: linux-mips@linux-mips.org
Cc: linux-kernel@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/13159/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
(cherry picked from commit db57f29d50683afd75c7f8b9908af7669837c3a9)
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
This commit is contained in:
parent
d3154ef703
commit
f67d2acc25
5 changed files with 25 additions and 19 deletions
|
@ -141,7 +141,8 @@ union ieee754sp ieee754sp_format(int sn, int xe, unsigned xm)
|
||||||
} else {
|
} else {
|
||||||
/* sticky right shift es bits
|
/* sticky right shift es bits
|
||||||
*/
|
*/
|
||||||
SPXSRSXn(es);
|
xm = XSPSRS(xm, es);
|
||||||
|
xe += es;
|
||||||
assert((xm & (SP_HIDDEN_BIT << 3)) == 0);
|
assert((xm & (SP_HIDDEN_BIT << 3)) == 0);
|
||||||
assert(xe == SP_EMIN);
|
assert(xe == SP_EMIN);
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,19 +46,17 @@ static inline int ieee754sp_finite(union ieee754sp x)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 3bit extended single precision sticky right shift */
|
/* 3bit extended single precision sticky right shift */
|
||||||
#define SPXSRSXn(rs) \
|
#define XSPSRS(v, rs) \
|
||||||
(xe += rs, \
|
((rs > (SP_FBITS+3))?1:((v) >> (rs)) | ((v) << (32-(rs)) != 0))
|
||||||
xm = (rs > (SP_FBITS+3))?1:((xm) >> (rs)) | ((xm) << (32-(rs)) != 0))
|
|
||||||
|
#define XSPSRS1(m) \
|
||||||
|
((m >> 1) | (m & 1))
|
||||||
|
|
||||||
#define SPXSRSX1() \
|
#define SPXSRSX1() \
|
||||||
(xe++, (xm = (xm >> 1) | (xm & 1)))
|
(xe++, (xm = XSPSRS1(xm)))
|
||||||
|
|
||||||
#define SPXSRSYn(rs) \
|
|
||||||
(ye+=rs, \
|
|
||||||
ym = (rs > (SP_FBITS+3))?1:((ym) >> (rs)) | ((ym) << (32-(rs)) != 0))
|
|
||||||
|
|
||||||
#define SPXSRSY1() \
|
#define SPXSRSY1() \
|
||||||
(ye++, (ym = (ym >> 1) | (ym & 1)))
|
(ye++, (ym = XSPSRS1(ym)))
|
||||||
|
|
||||||
/* convert denormal to normalized with extended exponent */
|
/* convert denormal to normalized with extended exponent */
|
||||||
#define SPDNORMx(m,e) \
|
#define SPDNORMx(m,e) \
|
||||||
|
|
|
@ -132,13 +132,15 @@ union ieee754sp ieee754sp_add(union ieee754sp x, union ieee754sp y)
|
||||||
* Have to shift y fraction right to align.
|
* Have to shift y fraction right to align.
|
||||||
*/
|
*/
|
||||||
s = xe - ye;
|
s = xe - ye;
|
||||||
SPXSRSYn(s);
|
ym = XSPSRS(ym, s);
|
||||||
|
ye += s;
|
||||||
} else if (ye > xe) {
|
} else if (ye > xe) {
|
||||||
/*
|
/*
|
||||||
* Have to shift x fraction right to align.
|
* Have to shift x fraction right to align.
|
||||||
*/
|
*/
|
||||||
s = ye - xe;
|
s = ye - xe;
|
||||||
SPXSRSXn(s);
|
xm = XSPSRS(xm, s);
|
||||||
|
xe += s;
|
||||||
}
|
}
|
||||||
assert(xe == ye);
|
assert(xe == ye);
|
||||||
assert(xe <= SP_EMAX);
|
assert(xe <= SP_EMAX);
|
||||||
|
|
|
@ -214,16 +214,18 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
|
||||||
|
|
||||||
if (ze > re) {
|
if (ze > re) {
|
||||||
/*
|
/*
|
||||||
* Have to shift y fraction right to align.
|
* Have to shift r fraction right to align.
|
||||||
*/
|
*/
|
||||||
s = ze - re;
|
s = ze - re;
|
||||||
SPXSRSYn(s);
|
rm = XSPSRS(rm, s);
|
||||||
|
re += s;
|
||||||
} else if (re > ze) {
|
} else if (re > ze) {
|
||||||
/*
|
/*
|
||||||
* Have to shift x fraction right to align.
|
* Have to shift z fraction right to align.
|
||||||
*/
|
*/
|
||||||
s = re - ze;
|
s = re - ze;
|
||||||
SPXSRSYn(s);
|
zm = XSPSRS(zm, s);
|
||||||
|
ze += s;
|
||||||
}
|
}
|
||||||
assert(ze == re);
|
assert(ze == re);
|
||||||
assert(ze <= SP_EMAX);
|
assert(ze <= SP_EMAX);
|
||||||
|
@ -236,7 +238,8 @@ static union ieee754sp _sp_maddf(union ieee754sp z, union ieee754sp x,
|
||||||
zm = zm + rm;
|
zm = zm + rm;
|
||||||
|
|
||||||
if (zm >> (SP_FBITS + 1 + 3)) { /* carry out */
|
if (zm >> (SP_FBITS + 1 + 3)) { /* carry out */
|
||||||
SPXSRSX1();
|
zm = XSPSRS1(zm);
|
||||||
|
ze++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (zm >= rm) {
|
if (zm >= rm) {
|
||||||
|
|
|
@ -134,13 +134,15 @@ union ieee754sp ieee754sp_sub(union ieee754sp x, union ieee754sp y)
|
||||||
* have to shift y fraction right to align
|
* have to shift y fraction right to align
|
||||||
*/
|
*/
|
||||||
s = xe - ye;
|
s = xe - ye;
|
||||||
SPXSRSYn(s);
|
ym = XSPSRS(ym, s);
|
||||||
|
ye += s;
|
||||||
} else if (ye > xe) {
|
} else if (ye > xe) {
|
||||||
/*
|
/*
|
||||||
* have to shift x fraction right to align
|
* have to shift x fraction right to align
|
||||||
*/
|
*/
|
||||||
s = ye - xe;
|
s = ye - xe;
|
||||||
SPXSRSXn(s);
|
xm = XSPSRS(xm, s);
|
||||||
|
xe += s;
|
||||||
}
|
}
|
||||||
assert(xe == ye);
|
assert(xe == ye);
|
||||||
assert(xe <= SP_EMAX);
|
assert(xe <= SP_EMAX);
|
||||||
|
|
Loading…
Add table
Reference in a new issue