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

fcnvfu.c (11711B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Linux/PA-RISC Project (http://www.parisc-linux.org/)
      4 *
      5 * Floating-point emulation code
      6 *  Copyright (C) 2001 Hewlett-Packard (Paul Bame) <bame@debian.org>
      7 */
      8/*
      9 * BEGIN_DESC
     10 *
     11 *  File:
     12 *	@(#)	pa/spmath/fcnvfu.c		$Revision: 1.1 $
     13 *
     14 *  Purpose:
     15 *	Floating-point to Unsigned Fixed-point Converts
     16 *
     17 *  External Interfaces:
     18 *	dbl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status)
     19 *	dbl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status)
     20 *	sgl_to_dbl_fcnvfu(srcptr,nullptr,dstptr,status)
     21 *	sgl_to_sgl_fcnvfu(srcptr,nullptr,dstptr,status)
     22 *
     23 *  Internal Interfaces:
     24 *
     25 *  Theory:
     26 *	<<please update with a overview of the operation of this file>>
     27 *
     28 * END_DESC
     29*/
     30
     31
     32#include "float.h"
     33#include "sgl_float.h"
     34#include "dbl_float.h"
     35#include "cnv_float.h"
     36
     37/************************************************************************
     38 *  Floating-point to Unsigned Fixed-point Converts			*
     39 ************************************************************************/
     40
     41/*
     42 *  Single Floating-point to Single Unsigned Fixed 
     43 */
     44/*ARGSUSED*/
     45int
     46sgl_to_sgl_fcnvfu(
     47			sgl_floating_point *srcptr,
     48			unsigned int *nullptr,
     49			unsigned int *dstptr,
     50			unsigned int *status)
     51{
     52	register unsigned int src, result;
     53	register int src_exponent;
     54	register boolean inexact = FALSE;
     55
     56	src = *srcptr;
     57	src_exponent = Sgl_exponent(src) - SGL_BIAS;
     58
     59	/* 
     60	 * Test for overflow
     61	 */
     62	if (src_exponent > SGL_FX_MAX_EXP + 1) {
     63		if (Sgl_isone_sign(src)) {
     64			result = 0;
     65		} else {
     66			result = 0xffffffff;
     67		}
     68		if (Is_invalidtrap_enabled()) {
     69			return(INVALIDEXCEPTION);
     70		}
     71		Set_invalidflag();
     72		*dstptr = result;
     73		return(NOEXCEPTION);
     74	}
     75	/*
     76	 * Generate result
     77	 */
     78	if (src_exponent >= 0) {
     79		/* 
     80		 * Check sign.
     81		 * If negative, trap unimplemented.
     82		 */
     83		if (Sgl_isone_sign(src)) {
     84			result = 0;
     85			if (Is_invalidtrap_enabled()) {
     86				return(INVALIDEXCEPTION);
     87			}
     88			Set_invalidflag();
     89			*dstptr = result;
     90			return(NOEXCEPTION);
     91		}
     92		Sgl_clear_signexponent_set_hidden(src);
     93		Suint_from_sgl_mantissa(src,src_exponent,result);
     94
     95		/* check for inexact */
     96		if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
     97			inexact = TRUE;
     98			/*  round result  */
     99			switch (Rounding_mode()) {
    100			case ROUNDPLUS:
    101				result++;
    102				break;
    103			case ROUNDMINUS: /* never negative */
    104				break;
    105			case ROUNDNEAREST:
    106				if (Sgl_isone_roundbit(src,src_exponent) &&
    107				    (Sgl_isone_stickybit(src,src_exponent) ||
    108				     (result & 1))) {
    109			     		result++;
    110				}
    111				break;
    112			}
    113		}
    114	} else {
    115		result = 0;
    116
    117		/* check for inexact */
    118		if (Sgl_isnotzero_exponentmantissa(src)) {
    119			inexact = TRUE;
    120			/*  round result  */
    121			switch (Rounding_mode()) {
    122			case ROUNDPLUS:
    123				if (Sgl_iszero_sign(src)) {
    124					result++;
    125				}
    126				break;
    127			case ROUNDMINUS:
    128				if (Sgl_isone_sign(src)) {
    129					result = 0;
    130					if (Is_invalidtrap_enabled()) {
    131						return(INVALIDEXCEPTION);
    132					}
    133					Set_invalidflag();
    134					inexact = FALSE;
    135				}
    136				break;
    137			case ROUNDNEAREST:
    138				if (src_exponent == -1 &&
    139				    Sgl_isnotzero_mantissa(src)) {
    140					if (Sgl_isone_sign(src)) {
    141						result = 0;
    142						if (Is_invalidtrap_enabled()) {
    143							return(INVALIDEXCEPTION);
    144						}
    145						Set_invalidflag();
    146						inexact = FALSE;
    147					}
    148			      		else result++;
    149				}
    150				break;
    151			}
    152		}
    153	}
    154	*dstptr = result;
    155	if (inexact) {
    156		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
    157		else Set_inexactflag();
    158	}
    159	return(NOEXCEPTION);
    160}
    161
    162/*
    163 *  Single Floating-point to Double Unsigned Fixed 
    164 */
    165/*ARGSUSED*/
    166int
    167sgl_to_dbl_fcnvfu(
    168		    sgl_floating_point *srcptr,
    169		    unsigned int *nullptr,
    170		    dbl_unsigned *dstptr,
    171		    unsigned int *status)
    172{
    173	register int src_exponent;
    174	register unsigned int src, resultp1, resultp2;
    175	register boolean inexact = FALSE;
    176
    177	src = *srcptr;
    178	src_exponent = Sgl_exponent(src) - SGL_BIAS;
    179
    180	/* 
    181	 * Test for overflow
    182	 */
    183	if (src_exponent > DBL_FX_MAX_EXP + 1) {
    184		if (Sgl_isone_sign(src)) {
    185			resultp1 = resultp2 = 0;
    186		} else {
    187			resultp1 = resultp2 = 0xffffffff;
    188		}
    189		if (Is_invalidtrap_enabled()) {
    190			return(INVALIDEXCEPTION);
    191		}
    192		Set_invalidflag();
    193    		Duint_copytoptr(resultp1,resultp2,dstptr);
    194		return(NOEXCEPTION);
    195	}
    196	/*
    197	 * Generate result
    198	 */
    199	if (src_exponent >= 0) {
    200		/* 
    201		 * Check sign.
    202		 * If negative, trap unimplemented.
    203		 */
    204		if (Sgl_isone_sign(src)) {
    205			resultp1 = resultp2 = 0;
    206			if (Is_invalidtrap_enabled()) {
    207				return(INVALIDEXCEPTION);
    208			}
    209			Set_invalidflag();
    210    			Duint_copytoptr(resultp1,resultp2,dstptr);
    211			return(NOEXCEPTION);
    212		}
    213		Sgl_clear_signexponent_set_hidden(src);
    214		Duint_from_sgl_mantissa(src,src_exponent,resultp1,resultp2);
    215
    216		/* check for inexact */
    217		if (Sgl_isinexact_to_unsigned(src,src_exponent)) {
    218			inexact = TRUE;
    219			/*  round result  */
    220			switch (Rounding_mode()) {
    221			case ROUNDPLUS:
    222				Duint_increment(resultp1,resultp2);
    223				break;
    224			case ROUNDMINUS: /* never negative */
    225				break;
    226			case ROUNDNEAREST:
    227				if (Sgl_isone_roundbit(src,src_exponent) &&
    228				    (Sgl_isone_stickybit(src,src_exponent) || 
    229				     Duint_isone_lowp2(resultp2))) {
    230					Duint_increment(resultp1,resultp2);
    231				}
    232				break;
    233			}
    234		}
    235	} else {
    236		Duint_setzero(resultp1,resultp2);
    237
    238		/* check for inexact */
    239		if (Sgl_isnotzero_exponentmantissa(src)) {
    240			inexact = TRUE;
    241			/*  round result  */
    242			switch (Rounding_mode()) {
    243			case ROUNDPLUS:
    244				if (Sgl_iszero_sign(src)) {
    245					Duint_increment(resultp1,resultp2);
    246				}
    247				break;
    248			case ROUNDMINUS:
    249				if (Sgl_isone_sign(src)) {
    250					resultp1 = resultp2 = 0;
    251					if (Is_invalidtrap_enabled()) {
    252						return(INVALIDEXCEPTION);
    253					}
    254					Set_invalidflag();
    255					inexact = FALSE;
    256				}
    257				break;
    258			case ROUNDNEAREST:
    259				if (src_exponent == -1 &&
    260				    Sgl_isnotzero_mantissa(src)) {
    261					if (Sgl_isone_sign(src)) {
    262						resultp1 = 0;
    263						resultp2 = 0;
    264						if (Is_invalidtrap_enabled()) {
    265							return(INVALIDEXCEPTION);
    266						}
    267						Set_invalidflag();
    268						inexact = FALSE;
    269					}
    270					else Duint_increment(resultp1,resultp2);
    271				}
    272			}
    273		}
    274	}
    275	Duint_copytoptr(resultp1,resultp2,dstptr);
    276	if (inexact) {
    277		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
    278		else Set_inexactflag();
    279	}
    280	return(NOEXCEPTION);
    281}
    282
    283/*
    284 *  Double Floating-point to Single Unsigned Fixed 
    285 */
    286/*ARGSUSED*/
    287int
    288dbl_to_sgl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr,
    289		   unsigned int *dstptr, unsigned int *status)
    290{
    291	register unsigned int srcp1, srcp2, result;
    292	register int src_exponent;
    293	register boolean inexact = FALSE;
    294
    295	Dbl_copyfromptr(srcptr,srcp1,srcp2);
    296	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
    297
    298	/* 
    299	 * Test for overflow
    300	 */
    301	if (src_exponent > SGL_FX_MAX_EXP + 1) {
    302		if (Dbl_isone_sign(srcp1)) {
    303			result = 0;
    304		} else {
    305			result = 0xffffffff;
    306		}
    307		if (Is_invalidtrap_enabled()) {
    308			return(INVALIDEXCEPTION);
    309		}
    310		Set_invalidflag();
    311		*dstptr = result;
    312		return(NOEXCEPTION);
    313	}
    314	/*
    315	 * Generate result
    316	 */
    317	if (src_exponent >= 0) {
    318		/* 
    319		 * Check sign.
    320		 * If negative, trap unimplemented.
    321		 */
    322		if (Dbl_isone_sign(srcp1)) {
    323			result = 0;
    324			if (Is_invalidtrap_enabled()) {
    325				return(INVALIDEXCEPTION);
    326			}
    327			Set_invalidflag();
    328			*dstptr = result;
    329			return(NOEXCEPTION);
    330		}
    331		Dbl_clear_signexponent_set_hidden(srcp1);
    332		Suint_from_dbl_mantissa(srcp1,srcp2,src_exponent,result);
    333
    334		/* check for inexact */
    335		if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
    336			inexact = TRUE;
    337			/*  round result  */
    338			switch (Rounding_mode()) {
    339			case ROUNDPLUS:
    340			     result++;
    341			     break;
    342			case ROUNDMINUS: /* never negative */
    343			     break;
    344			case ROUNDNEAREST:
    345			     if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent) &&
    346				(Dbl_isone_stickybit(srcp1,srcp2,src_exponent)||
    347				 result&1))
    348				   result++;
    349			     break;
    350			}
    351			/* check for overflow */
    352			if (result == 0) {
    353				result = 0xffffffff;
    354				if (Is_invalidtrap_enabled()) {
    355					return(INVALIDEXCEPTION);
    356				}
    357				Set_invalidflag();
    358				*dstptr = result;
    359				return(NOEXCEPTION);
    360			}
    361		}
    362	} else {
    363		result = 0;
    364
    365		/* check for inexact */
    366		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
    367			inexact = TRUE;
    368			/*  round result  */
    369			switch (Rounding_mode()) {
    370			case ROUNDPLUS:
    371				if (Dbl_iszero_sign(srcp1)) result++;
    372				break;
    373			case ROUNDMINUS:
    374				if (Dbl_isone_sign(srcp1)) {
    375					result = 0;
    376					if (Is_invalidtrap_enabled()) {
    377						return(INVALIDEXCEPTION);
    378					}
    379					Set_invalidflag();
    380					inexact = FALSE;
    381				}
    382				break;
    383			case ROUNDNEAREST:
    384				if (src_exponent == -1 &&
    385				    Dbl_isnotzero_mantissa(srcp1,srcp2))
    386					if (Dbl_isone_sign(srcp1)) {
    387						result = 0;
    388						if (Is_invalidtrap_enabled()) {
    389							return(INVALIDEXCEPTION);
    390						}
    391						Set_invalidflag();
    392						inexact = FALSE;
    393					}
    394					else result++;
    395			}
    396		}
    397	}
    398	*dstptr = result;
    399	if (inexact) {
    400		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
    401		else Set_inexactflag();
    402	}
    403	return(NOEXCEPTION);
    404}
    405
    406/*
    407 *  Double Floating-point to Double Unsigned Fixed 
    408 */
    409/*ARGSUSED*/
    410int
    411dbl_to_dbl_fcnvfu (dbl_floating_point * srcptr, unsigned int *nullptr,
    412		   dbl_unsigned * dstptr, unsigned int *status)
    413{
    414	register int src_exponent;
    415	register unsigned int srcp1, srcp2, resultp1, resultp2;
    416	register boolean inexact = FALSE;
    417
    418	Dbl_copyfromptr(srcptr,srcp1,srcp2);
    419	src_exponent = Dbl_exponent(srcp1) - DBL_BIAS;
    420
    421	/* 
    422	 * Test for overflow
    423	 */
    424	if (src_exponent > DBL_FX_MAX_EXP + 1) {
    425		if (Dbl_isone_sign(srcp1)) {
    426			resultp1 = resultp2 = 0;
    427		} else {
    428			resultp1 = resultp2 = 0xffffffff;
    429		}
    430		if (Is_invalidtrap_enabled()) {
    431			return(INVALIDEXCEPTION);
    432		}
    433		Set_invalidflag();
    434    		Duint_copytoptr(resultp1,resultp2,dstptr);
    435		return(NOEXCEPTION);
    436	}
    437 
    438	/*
    439	 * Generate result
    440	 */
    441	if (src_exponent >= 0) {
    442		/* 
    443		 * Check sign.
    444		 * If negative, trap unimplemented.
    445		 */
    446		if (Dbl_isone_sign(srcp1)) {
    447			resultp1 = resultp2 = 0;
    448			if (Is_invalidtrap_enabled()) {
    449				return(INVALIDEXCEPTION);
    450			}
    451			Set_invalidflag();
    452    			Duint_copytoptr(resultp1,resultp2,dstptr);
    453			return(NOEXCEPTION);
    454		}
    455		Dbl_clear_signexponent_set_hidden(srcp1);
    456		Duint_from_dbl_mantissa(srcp1,srcp2,src_exponent,resultp1,
    457		  resultp2);
    458
    459		/* check for inexact */
    460		if (Dbl_isinexact_to_unsigned(srcp1,srcp2,src_exponent)) {
    461			inexact = TRUE;
    462			/*  round result  */
    463			switch (Rounding_mode()) {
    464			case ROUNDPLUS:
    465				Duint_increment(resultp1,resultp2);
    466				break;
    467			case ROUNDMINUS: /* never negative */
    468				break;
    469			case ROUNDNEAREST:
    470				if(Dbl_isone_roundbit(srcp1,srcp2,src_exponent))
    471				  if(Dbl_isone_stickybit(srcp1,srcp2,src_exponent) || 
    472				     Duint_isone_lowp2(resultp2))
    473					Duint_increment(resultp1,resultp2);
    474			} 
    475		}
    476	} else {
    477		Duint_setzero(resultp1,resultp2);
    478
    479		/* check for inexact */
    480		if (Dbl_isnotzero_exponentmantissa(srcp1,srcp2)) {
    481			inexact = TRUE;
    482			/*  round result  */
    483			switch (Rounding_mode()) {
    484			case ROUNDPLUS:
    485				if (Dbl_iszero_sign(srcp1)) {
    486					Duint_increment(resultp1,resultp2);
    487				}
    488				break;
    489			case ROUNDMINUS:
    490				if (Dbl_isone_sign(srcp1)) {
    491					resultp1 = resultp2 = 0;
    492					if (Is_invalidtrap_enabled()) {
    493						return(INVALIDEXCEPTION);
    494					}
    495					Set_invalidflag();
    496					inexact = FALSE;
    497				}
    498				break;
    499			case ROUNDNEAREST:
    500				if (src_exponent == -1 &&
    501				    Dbl_isnotzero_mantissa(srcp1,srcp2))
    502					if (Dbl_iszero_sign(srcp1)) {
    503						Duint_increment(resultp1,resultp2);
    504					} else {
    505						resultp1 = 0;
    506						resultp2 = 0;
    507						if (Is_invalidtrap_enabled()) {
    508							return(INVALIDEXCEPTION);
    509						}
    510						Set_invalidflag();
    511						inexact = FALSE;
    512					}
    513			}
    514		}
    515	}
    516	Duint_copytoptr(resultp1,resultp2,dstptr);
    517	if (inexact) {
    518		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
    519		else Set_inexactflag();
    520	}
    521	return(NOEXCEPTION);
    522}
    523