162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/* IEEE754 floating point arithmetic
362306a36Sopenharmony_ci * single precision
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci/*
662306a36Sopenharmony_ci * MIPS floating point support
762306a36Sopenharmony_ci * Copyright (C) 1994-2000 Algorithmics Ltd.
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include "ieee754sp.h"
1162306a36Sopenharmony_ci#include "ieee754dp.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cistatic inline union ieee754sp ieee754sp_nan_fdp(int xs, u64 xm)
1462306a36Sopenharmony_ci{
1562306a36Sopenharmony_ci	return buildsp(xs, SP_EMAX + 1 + SP_EBIAS,
1662306a36Sopenharmony_ci		       xm >> (DP_FBITS - SP_FBITS));
1762306a36Sopenharmony_ci}
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ciunion ieee754sp ieee754sp_fdp(union ieee754dp x)
2062306a36Sopenharmony_ci{
2162306a36Sopenharmony_ci	union ieee754sp y;
2262306a36Sopenharmony_ci	u32 rm;
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci	COMPXDP;
2562306a36Sopenharmony_ci	COMPYSP;
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_ci	EXPLODEXDP;
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	ieee754_clearcx();
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci	FLUSHXDP;
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci	switch (xc) {
3462306a36Sopenharmony_ci	case IEEE754_CLASS_SNAN:
3562306a36Sopenharmony_ci		x = ieee754dp_nanxcpt(x);
3662306a36Sopenharmony_ci		EXPLODEXDP;
3762306a36Sopenharmony_ci		fallthrough;
3862306a36Sopenharmony_ci	case IEEE754_CLASS_QNAN:
3962306a36Sopenharmony_ci		y = ieee754sp_nan_fdp(xs, xm);
4062306a36Sopenharmony_ci		if (!ieee754_csr.nan2008) {
4162306a36Sopenharmony_ci			EXPLODEYSP;
4262306a36Sopenharmony_ci			if (!ieee754_class_nan(yc))
4362306a36Sopenharmony_ci				y = ieee754sp_indef();
4462306a36Sopenharmony_ci		}
4562306a36Sopenharmony_ci		return y;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	case IEEE754_CLASS_INF:
4862306a36Sopenharmony_ci		return ieee754sp_inf(xs);
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	case IEEE754_CLASS_ZERO:
5162306a36Sopenharmony_ci		return ieee754sp_zero(xs);
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	case IEEE754_CLASS_DNORM:
5462306a36Sopenharmony_ci		/* can't possibly be sp representable */
5562306a36Sopenharmony_ci		ieee754_setcx(IEEE754_UNDERFLOW);
5662306a36Sopenharmony_ci		ieee754_setcx(IEEE754_INEXACT);
5762306a36Sopenharmony_ci		if ((ieee754_csr.rm == FPU_CSR_RU && !xs) ||
5862306a36Sopenharmony_ci				(ieee754_csr.rm == FPU_CSR_RD && xs))
5962306a36Sopenharmony_ci			return ieee754sp_mind(xs);
6062306a36Sopenharmony_ci		return ieee754sp_zero(xs);
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	case IEEE754_CLASS_NORM:
6362306a36Sopenharmony_ci		break;
6462306a36Sopenharmony_ci	}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	/*
6762306a36Sopenharmony_ci	 * Convert from DP_FBITS to SP_FBITS+3 with sticky right shift.
6862306a36Sopenharmony_ci	 */
6962306a36Sopenharmony_ci	rm = (xm >> (DP_FBITS - (SP_FBITS + 3))) |
7062306a36Sopenharmony_ci	     ((xm << (64 - (DP_FBITS - (SP_FBITS + 3)))) != 0);
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	return ieee754sp_format(xs, xe, rm);
7362306a36Sopenharmony_ci}
74