| // SPDX-License-Identifier: GPL-2.0-only | 
 | /* IEEE754 floating point arithmetic | 
 |  * double precision: common utilities | 
 |  */ | 
 | /* | 
 |  * MIPS floating point support | 
 |  * Copyright (C) 1994-2000 Algorithmics Ltd. | 
 |  */ | 
 |  | 
 | #include "ieee754dp.h" | 
 |  | 
 | union ieee754dp ieee754dp_add(union ieee754dp x, union ieee754dp y) | 
 | { | 
 | 	int s; | 
 |  | 
 | 	COMPXDP; | 
 | 	COMPYDP; | 
 |  | 
 | 	EXPLODEXDP; | 
 | 	EXPLODEYDP; | 
 |  | 
 | 	ieee754_clearcx(); | 
 |  | 
 | 	FLUSHXDP; | 
 | 	FLUSHYDP; | 
 |  | 
 | 	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 ieee754dp_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 ieee754dp_nanxcpt(x); | 
 |  | 
 | 	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 y; | 
 |  | 
 | 	case CLPAIR(IEEE754_CLASS_QNAN, IEEE754_CLASS_QNAN): | 
 | 	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 x; | 
 |  | 
 |  | 
 | 	/* | 
 | 	 * Infinity handling | 
 | 	 */ | 
 | 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_INF): | 
 | 		if (xs == ys) | 
 | 			return x; | 
 | 		ieee754_setcx(IEEE754_INVALID_OPERATION); | 
 | 		return ieee754dp_indef(); | 
 |  | 
 | 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_INF): | 
 | 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_INF): | 
 | 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_INF): | 
 | 		return y; | 
 |  | 
 | 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_ZERO): | 
 | 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_NORM): | 
 | 	case CLPAIR(IEEE754_CLASS_INF, IEEE754_CLASS_DNORM): | 
 | 		return x; | 
 |  | 
 | 	/* | 
 | 	 * Zero handling | 
 | 	 */ | 
 | 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_ZERO): | 
 | 		if (xs == ys) | 
 | 			return x; | 
 | 		else | 
 | 			return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD); | 
 |  | 
 | 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_ZERO): | 
 | 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_ZERO): | 
 | 		return x; | 
 |  | 
 | 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_NORM): | 
 | 	case CLPAIR(IEEE754_CLASS_ZERO, IEEE754_CLASS_DNORM): | 
 | 		return y; | 
 |  | 
 | 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_DNORM): | 
 | 		DPDNORMX; | 
 | 		fallthrough; | 
 | 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_DNORM): | 
 | 		DPDNORMY; | 
 | 		break; | 
 |  | 
 | 	case CLPAIR(IEEE754_CLASS_DNORM, IEEE754_CLASS_NORM): | 
 | 		DPDNORMX; | 
 | 		break; | 
 |  | 
 | 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM): | 
 | 		break; | 
 | 	} | 
 | 	assert(xm & DP_HIDDEN_BIT); | 
 | 	assert(ym & DP_HIDDEN_BIT); | 
 |  | 
 | 	/* | 
 | 	 * Provide guard,round and stick bit space. | 
 | 	 */ | 
 | 	xm <<= 3; | 
 | 	ym <<= 3; | 
 |  | 
 | 	if (xe > ye) { | 
 | 		/* | 
 | 		 * Have to shift y fraction right to align. | 
 | 		 */ | 
 | 		s = xe - ye; | 
 | 		ym = XDPSRS(ym, s); | 
 | 		ye += s; | 
 | 	} else if (ye > xe) { | 
 | 		/* | 
 | 		 * Have to shift x fraction right to align. | 
 | 		 */ | 
 | 		s = ye - xe; | 
 | 		xm = XDPSRS(xm, s); | 
 | 		xe += s; | 
 | 	} | 
 | 	assert(xe == ye); | 
 | 	assert(xe <= DP_EMAX); | 
 |  | 
 | 	if (xs == ys) { | 
 | 		/* | 
 | 		 * Generate 28 bit result of adding two 27 bit numbers | 
 | 		 * leaving result in xm, xs and xe. | 
 | 		 */ | 
 | 		xm = xm + ym; | 
 |  | 
 | 		if (xm >> (DP_FBITS + 1 + 3)) { /* carry out */ | 
 | 			xm = XDPSRS1(xm); | 
 | 			xe++; | 
 | 		} | 
 | 	} else { | 
 | 		if (xm >= ym) { | 
 | 			xm = xm - ym; | 
 | 		} else { | 
 | 			xm = ym - xm; | 
 | 			xs = ys; | 
 | 		} | 
 | 		if (xm == 0) | 
 | 			return ieee754dp_zero(ieee754_csr.rm == FPU_CSR_RD); | 
 |  | 
 | 		/* | 
 | 		 * Normalize to rounding precision. | 
 | 		 */ | 
 | 		while ((xm >> (DP_FBITS + 3)) == 0) { | 
 | 			xm <<= 1; | 
 | 			xe--; | 
 | 		} | 
 | 	} | 
 |  | 
 | 	return ieee754dp_format(xs, xe, xm); | 
 | } |