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

fcnvfx.c (14373B)


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