| // SPDX-License-Identifier: GPL-2.0-only |
| /* |
| * IEEE754 floating point arithmetic |
| * single precision: MIN{,A}.f |
| * MIN : Scalar Floating-Point Minimum |
| * MINA: Scalar Floating-Point argument with Minimum Absolute Value |
| * |
| * MIN.S : FPR[fd] = minNum(FPR[fs],FPR[ft]) |
| * MINA.S: FPR[fd] = maxNumMag(FPR[fs],FPR[ft]) |
| * |
| * MIPS floating point support |
| * Copyright (C) 2015 Imagination Technologies, Ltd. |
| * Author: Markos Chandras <markos.chandras@imgtec.com> |
| */ |
| |
| #include "ieee754sp.h" |
| |
| union ieee754sp ieee754sp_fmin(union ieee754sp x, union ieee754sp y) |
| { |
| COMPXSP; |
| COMPYSP; |
| |
| EXPLODEXSP; |
| EXPLODEYSP; |
| |
| FLUSHXSP; |
| FLUSHYSP; |
| |
| ieee754_clearcx(); |
| |
| switch (CLPAIR(xc, yc)) { |
| case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): |
| case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): |
| case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): |
| case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): |
| case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): |
| return ieee754sp_nanxcpt(y); |
| |
| case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): |
| case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): |
| case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): |
| case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): |
| case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): |
| case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): |
| return ieee754sp_nanxcpt(x); |
| |
| /* |
| * Quiet NaN handling |
| */ |
| |
| /* |
| * The case of both inputs quiet NaNs |
| */ |
| case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): |
| return x; |
| |
| /* |
| * The cases of exactly one input quiet NaN (numbers |
| * are here preferred as returned values to NaNs) |
| */ |
| case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): |
| case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): |
| case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): |
| case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): |
| return x; |
| |
| case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): |
| case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): |
| case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): |
| case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): |
| return y; |
| |
| /* |
| * Infinity and zero handling |
| */ |
| case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): |
| case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): |
| case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): |
| case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): |
| case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): |
| return xs ? x : y; |
| |
| case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): |
| case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): |
| case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): |
| case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): |
| case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): |
| case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): |
| return ys ? y : x; |
| |
| case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): |
| return ieee754sp_zero(xs | ys); |
| |
| case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): |
| SPDNORMX; |
| /* fall through */ |
| |
| case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): |
| SPDNORMY; |
| break; |
| |
| case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): |
| SPDNORMX; |
| } |
| |
| /* Finally get to do some computation */ |
| |
| assert(xm & SP_HIDDEN_BIT); |
| assert(ym & SP_HIDDEN_BIT); |
| |
| /* Compare signs */ |
| if (xs > ys) |
| return x; |
| else if (xs < ys) |
| return y; |
| |
| /* Signs of inputs are the same, let's compare exponents */ |
| if (xs == 0) { |
| /* Inputs are both positive */ |
| if (xe > ye) |
| return y; |
| else if (xe < ye) |
| return x; |
| } else { |
| /* Inputs are both negative */ |
| if (xe > ye) |
| return x; |
| else if (xe < ye) |
| return y; |
| } |
| |
| /* Signs and exponents of inputs are equal, let's compare mantissas */ |
| if (xs == 0) { |
| /* Inputs are both positive, with equal signs and exponents */ |
| if (xm <= ym) |
| return x; |
| return y; |
| } |
| /* Inputs are both negative, with equal signs and exponents */ |
| if (xm <= ym) |
| return y; |
| return x; |
| } |
| |
| union ieee754sp ieee754sp_fmina(union ieee754sp x, union ieee754sp y) |
| { |
| COMPXSP; |
| COMPYSP; |
| |
| EXPLODEXSP; |
| EXPLODEYSP; |
| |
| FLUSHXSP; |
| FLUSHYSP; |
| |
| ieee754_clearcx(); |
| |
| switch (CLPAIR(xc, yc)) { |
| case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_SNAN): |
| case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_SNAN): |
| case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_SNAN): |
| case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_SNAN): |
| case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_SNAN): |
| return ieee754sp_nanxcpt(y); |
| |
| case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_SNAN): |
| case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_QNAN): |
| case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_ZERO): |
| case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_NORM): |
| case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_DNORM): |
| case CLPAIR(IEEE754_CLASS_SNAN, IEEE754_CLASS_INF): |
| return ieee754sp_nanxcpt(x); |
| |
| /* |
| * Quiet NaN handling |
| */ |
| |
| /* |
| * The case of both inputs quiet NaNs |
| */ |
| case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): |
| return x; |
| |
| /* |
| * The cases of exactly one input quiet NaN (numbers |
| * are here preferred as returned values to NaNs) |
| */ |
| case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_QNAN): |
| case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_QNAN): |
| case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_QNAN): |
| case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_QNAN): |
| return x; |
| |
| case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_ZERO): |
| case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_NORM): |
| case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_DNORM): |
| case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_INF): |
| return y; |
| |
| /* |
| * Infinity and zero handling |
| */ |
| case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): |
| return ieee754sp_inf(xs | ys); |
| |
| case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): |
| case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): |
| case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): |
| case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): |
| case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): |
| return y; |
| |
| case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): |
| case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): |
| case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): |
| case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): |
| case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): |
| return x; |
| |
| case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): |
| return ieee754sp_zero(xs | ys); |
| |
| case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): |
| SPDNORMX; |
| /* fall through */ |
| |
| case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): |
| SPDNORMY; |
| break; |
| |
| case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): |
| SPDNORMX; |
| } |
| |
| /* Finally get to do some computation */ |
| |
| assert(xm & SP_HIDDEN_BIT); |
| assert(ym & SP_HIDDEN_BIT); |
| |
| /* Compare exponent */ |
| if (xe > ye) |
| return y; |
| else if (xe < ye) |
| return x; |
| |
| /* Compare mantissa */ |
| if (xm < ym) |
| return x; |
| else if (xm > ym) |
| return y; |
| else if (xs == 1) |
| return x; |
| return y; |
| } |