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 * Copyright (C) 2017 Imagination Technologies, Ltd. 962306a36Sopenharmony_ci * Author: Aleksandar Markovic <aleksandar.markovic@imgtec.com> 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include "ieee754sp.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ciunion ieee754sp ieee754sp_rint(union ieee754sp x) 1562306a36Sopenharmony_ci{ 1662306a36Sopenharmony_ci union ieee754sp ret; 1762306a36Sopenharmony_ci u32 residue; 1862306a36Sopenharmony_ci int sticky; 1962306a36Sopenharmony_ci int round; 2062306a36Sopenharmony_ci int odd; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci COMPXDP; /* <-- DP needed for 64-bit mantissa tmp */ 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci ieee754_clearcx(); 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci EXPLODEXSP; 2762306a36Sopenharmony_ci FLUSHXSP; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci if (xc == IEEE754_CLASS_SNAN) 3062306a36Sopenharmony_ci return ieee754sp_nanxcpt(x); 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci if ((xc == IEEE754_CLASS_QNAN) || 3362306a36Sopenharmony_ci (xc == IEEE754_CLASS_INF) || 3462306a36Sopenharmony_ci (xc == IEEE754_CLASS_ZERO)) 3562306a36Sopenharmony_ci return x; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci if (xe >= SP_FBITS) 3862306a36Sopenharmony_ci return x; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci if (xe < -1) { 4162306a36Sopenharmony_ci residue = xm; 4262306a36Sopenharmony_ci round = 0; 4362306a36Sopenharmony_ci sticky = residue != 0; 4462306a36Sopenharmony_ci xm = 0; 4562306a36Sopenharmony_ci } else { 4662306a36Sopenharmony_ci residue = xm << (xe + 1); 4762306a36Sopenharmony_ci residue <<= 31 - SP_FBITS; 4862306a36Sopenharmony_ci round = (residue >> 31) != 0; 4962306a36Sopenharmony_ci sticky = (residue << 1) != 0; 5062306a36Sopenharmony_ci xm >>= SP_FBITS - xe; 5162306a36Sopenharmony_ci } 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci odd = (xm & 0x1) != 0x0; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci switch (ieee754_csr.rm) { 5662306a36Sopenharmony_ci case FPU_CSR_RN: /* toward nearest */ 5762306a36Sopenharmony_ci if (round && (sticky || odd)) 5862306a36Sopenharmony_ci xm++; 5962306a36Sopenharmony_ci break; 6062306a36Sopenharmony_ci case FPU_CSR_RZ: /* toward zero */ 6162306a36Sopenharmony_ci break; 6262306a36Sopenharmony_ci case FPU_CSR_RU: /* toward +infinity */ 6362306a36Sopenharmony_ci if ((round || sticky) && !xs) 6462306a36Sopenharmony_ci xm++; 6562306a36Sopenharmony_ci break; 6662306a36Sopenharmony_ci case FPU_CSR_RD: /* toward -infinity */ 6762306a36Sopenharmony_ci if ((round || sticky) && xs) 6862306a36Sopenharmony_ci xm++; 6962306a36Sopenharmony_ci break; 7062306a36Sopenharmony_ci } 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci if (round || sticky) 7362306a36Sopenharmony_ci ieee754_setcx(IEEE754_INEXACT); 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci ret = ieee754sp_flong(xm); 7662306a36Sopenharmony_ci SPSIGN(ret) = xs; 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci return ret; 7962306a36Sopenharmony_ci} 80