cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

ieee754sp.c (4349B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/* IEEE754 floating point arithmetic
      3 * single precision
      4 */
      5/*
      6 * MIPS floating point support
      7 * Copyright (C) 1994-2000 Algorithmics Ltd.
      8 */
      9
     10#include <linux/compiler.h>
     11
     12#include "ieee754sp.h"
     13
     14int ieee754sp_class(union ieee754sp x)
     15{
     16	COMPXSP;
     17	EXPLODEXSP;
     18	return xc;
     19}
     20
     21static inline int ieee754sp_isnan(union ieee754sp x)
     22{
     23	return ieee754_class_nan(ieee754sp_class(x));
     24}
     25
     26static inline int ieee754sp_issnan(union ieee754sp x)
     27{
     28	int qbit;
     29
     30	assert(ieee754sp_isnan(x));
     31	qbit = (SPMANT(x) & SP_MBIT(SP_FBITS - 1)) == SP_MBIT(SP_FBITS - 1);
     32	return ieee754_csr.nan2008 ^ qbit;
     33}
     34
     35
     36/*
     37 * Raise the Invalid Operation IEEE 754 exception
     38 * and convert the signaling NaN supplied to a quiet NaN.
     39 */
     40union ieee754sp __cold ieee754sp_nanxcpt(union ieee754sp r)
     41{
     42	assert(ieee754sp_issnan(r));
     43
     44	ieee754_setcx(IEEE754_INVALID_OPERATION);
     45	if (ieee754_csr.nan2008) {
     46		SPMANT(r) |= SP_MBIT(SP_FBITS - 1);
     47	} else {
     48		SPMANT(r) &= ~SP_MBIT(SP_FBITS - 1);
     49		if (!ieee754sp_isnan(r))
     50			SPMANT(r) |= SP_MBIT(SP_FBITS - 2);
     51	}
     52
     53	return r;
     54}
     55
     56static unsigned int ieee754sp_get_rounding(int sn, unsigned int xm)
     57{
     58	/* inexact must round of 3 bits
     59	 */
     60	if (xm & (SP_MBIT(3) - 1)) {
     61		switch (ieee754_csr.rm) {
     62		case FPU_CSR_RZ:
     63			break;
     64		case FPU_CSR_RN:
     65			xm += 0x3 + ((xm >> 3) & 1);
     66			/* xm += (xm&0x8)?0x4:0x3 */
     67			break;
     68		case FPU_CSR_RU:	/* toward +Infinity */
     69			if (!sn)	/* ?? */
     70				xm += 0x8;
     71			break;
     72		case FPU_CSR_RD:	/* toward -Infinity */
     73			if (sn) /* ?? */
     74				xm += 0x8;
     75			break;
     76		}
     77	}
     78	return xm;
     79}
     80
     81
     82/* generate a normal/denormal number with over,under handling
     83 * sn is sign
     84 * xe is an unbiased exponent
     85 * xm is 3bit extended precision value.
     86 */
     87union ieee754sp ieee754sp_format(int sn, int xe, unsigned int xm)
     88{
     89	assert(xm);		/* we don't gen exact zeros (probably should) */
     90
     91	assert((xm >> (SP_FBITS + 1 + 3)) == 0);	/* no excess */
     92	assert(xm & (SP_HIDDEN_BIT << 3));
     93
     94	if (xe < SP_EMIN) {
     95		/* strip lower bits */
     96		int es = SP_EMIN - xe;
     97
     98		if (ieee754_csr.nod) {
     99			ieee754_setcx(IEEE754_UNDERFLOW);
    100			ieee754_setcx(IEEE754_INEXACT);
    101
    102			switch(ieee754_csr.rm) {
    103			case FPU_CSR_RN:
    104			case FPU_CSR_RZ:
    105				return ieee754sp_zero(sn);
    106			case FPU_CSR_RU:      /* toward +Infinity */
    107				if (sn == 0)
    108					return ieee754sp_min(0);
    109				else
    110					return ieee754sp_zero(1);
    111			case FPU_CSR_RD:      /* toward -Infinity */
    112				if (sn == 0)
    113					return ieee754sp_zero(0);
    114				else
    115					return ieee754sp_min(1);
    116			}
    117		}
    118
    119		if (xe == SP_EMIN - 1 &&
    120		    ieee754sp_get_rounding(sn, xm) >> (SP_FBITS + 1 + 3))
    121		{
    122			/* Not tiny after rounding */
    123			ieee754_setcx(IEEE754_INEXACT);
    124			xm = ieee754sp_get_rounding(sn, xm);
    125			xm >>= 1;
    126			/* Clear grs bits */
    127			xm &= ~(SP_MBIT(3) - 1);
    128			xe++;
    129		} else {
    130			/* sticky right shift es bits
    131			 */
    132			xm = XSPSRS(xm, es);
    133			xe += es;
    134			assert((xm & (SP_HIDDEN_BIT << 3)) == 0);
    135			assert(xe == SP_EMIN);
    136		}
    137	}
    138	if (xm & (SP_MBIT(3) - 1)) {
    139		ieee754_setcx(IEEE754_INEXACT);
    140		if ((xm & (SP_HIDDEN_BIT << 3)) == 0) {
    141			ieee754_setcx(IEEE754_UNDERFLOW);
    142		}
    143
    144		/* inexact must round of 3 bits
    145		 */
    146		xm = ieee754sp_get_rounding(sn, xm);
    147		/* adjust exponent for rounding add overflowing
    148		 */
    149		if (xm >> (SP_FBITS + 1 + 3)) {
    150			/* add causes mantissa overflow */
    151			xm >>= 1;
    152			xe++;
    153		}
    154	}
    155	/* strip grs bits */
    156	xm >>= 3;
    157
    158	assert((xm >> (SP_FBITS + 1)) == 0);	/* no excess */
    159	assert(xe >= SP_EMIN);
    160
    161	if (xe > SP_EMAX) {
    162		ieee754_setcx(IEEE754_OVERFLOW);
    163		ieee754_setcx(IEEE754_INEXACT);
    164		/* -O can be table indexed by (rm,sn) */
    165		switch (ieee754_csr.rm) {
    166		case FPU_CSR_RN:
    167			return ieee754sp_inf(sn);
    168		case FPU_CSR_RZ:
    169			return ieee754sp_max(sn);
    170		case FPU_CSR_RU:	/* toward +Infinity */
    171			if (sn == 0)
    172				return ieee754sp_inf(0);
    173			else
    174				return ieee754sp_max(1);
    175		case FPU_CSR_RD:	/* toward -Infinity */
    176			if (sn == 0)
    177				return ieee754sp_max(0);
    178			else
    179				return ieee754sp_inf(1);
    180		}
    181	}
    182	/* gen norm/denorm/zero */
    183
    184	if ((xm & SP_HIDDEN_BIT) == 0) {
    185		/* we underflow (tiny/zero) */
    186		assert(xe == SP_EMIN);
    187		if (ieee754_csr.mx & IEEE754_UNDERFLOW)
    188			ieee754_setcx(IEEE754_UNDERFLOW);
    189		return buildsp(sn, SP_EMIN - 1 + SP_EBIAS, xm);
    190	} else {
    191		assert((xm >> (SP_FBITS + 1)) == 0);	/* no excess */
    192		assert(xm & SP_HIDDEN_BIT);
    193
    194		return buildsp(sn, xe + SP_EBIAS, xm & ~SP_HIDDEN_BIT);
    195	}
    196}