162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* IEEE754 floating point arithmetic 362306a36Sopenharmony_ci * double precision: common utilities 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 "ieee754dp.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ciunion ieee754dp ieee754dp_rint(union ieee754dp x) 1562306a36Sopenharmony_ci{ 1662306a36Sopenharmony_ci union ieee754dp ret; 1762306a36Sopenharmony_ci u64 residue; 1862306a36Sopenharmony_ci int sticky; 1962306a36Sopenharmony_ci int round; 2062306a36Sopenharmony_ci int odd; 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci COMPXDP; 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci ieee754_clearcx(); 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci EXPLODEXDP; 2762306a36Sopenharmony_ci FLUSHXDP; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci if (xc == IEEE754_CLASS_SNAN) 3062306a36Sopenharmony_ci return ieee754dp_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 >= DP_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 << (64 - DP_FBITS + xe); 4762306a36Sopenharmony_ci round = (residue >> 63) != 0; 4862306a36Sopenharmony_ci sticky = (residue << 1) != 0; 4962306a36Sopenharmony_ci xm >>= DP_FBITS - xe; 5062306a36Sopenharmony_ci } 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci odd = (xm & 0x1) != 0x0; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_ci switch (ieee754_csr.rm) { 5562306a36Sopenharmony_ci case FPU_CSR_RN: /* toward nearest */ 5662306a36Sopenharmony_ci if (round && (sticky || odd)) 5762306a36Sopenharmony_ci xm++; 5862306a36Sopenharmony_ci break; 5962306a36Sopenharmony_ci case FPU_CSR_RZ: /* toward zero */ 6062306a36Sopenharmony_ci break; 6162306a36Sopenharmony_ci case FPU_CSR_RU: /* toward +infinity */ 6262306a36Sopenharmony_ci if ((round || sticky) && !xs) 6362306a36Sopenharmony_ci xm++; 6462306a36Sopenharmony_ci break; 6562306a36Sopenharmony_ci case FPU_CSR_RD: /* toward -infinity */ 6662306a36Sopenharmony_ci if ((round || sticky) && xs) 6762306a36Sopenharmony_ci xm++; 6862306a36Sopenharmony_ci break; 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_ci if (round || sticky) 7262306a36Sopenharmony_ci ieee754_setcx(IEEE754_INEXACT); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci ret = ieee754dp_flong(xm); 7562306a36Sopenharmony_ci DPSIGN(ret) = xs; 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci return ret; 7862306a36Sopenharmony_ci} 79