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

sfdiv.c (10516B)


      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/sfdiv.c		$Revision: 1.1 $
     13 *
     14 *  Purpose:
     15 *	Single Precision Floating-point Divide
     16 *
     17 *  External Interfaces:
     18 *	sgl_fdiv(srcptr1,srcptr2,dstptr,status)
     19 *
     20 *  Internal Interfaces:
     21 *
     22 *  Theory:
     23 *	<<please update with a overview of the operation of this file>>
     24 *
     25 * END_DESC
     26*/
     27
     28
     29#include "float.h"
     30#include "sgl_float.h"
     31
     32/*
     33 *  Single Precision Floating-point Divide
     34 */
     35
     36int
     37sgl_fdiv (sgl_floating_point * srcptr1, sgl_floating_point * srcptr2,
     38	  sgl_floating_point * dstptr, unsigned int *status)
     39{
     40	register unsigned int opnd1, opnd2, opnd3, result;
     41	register int dest_exponent, count;
     42	register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE;
     43	boolean is_tiny;
     44
     45	opnd1 = *srcptr1;
     46	opnd2 = *srcptr2;
     47	/* 
     48	 * set sign bit of result 
     49	 */
     50	if (Sgl_sign(opnd1) ^ Sgl_sign(opnd2)) Sgl_setnegativezero(result);  
     51	else Sgl_setzero(result);
     52	/*
     53	 * check first operand for NaN's or infinity
     54	 */
     55	if (Sgl_isinfinity_exponent(opnd1)) {
     56		if (Sgl_iszero_mantissa(opnd1)) {
     57			if (Sgl_isnotnan(opnd2)) {
     58				if (Sgl_isinfinity(opnd2)) {
     59					/* 
     60					 * invalid since both operands 
     61					 * are infinity 
     62					 */
     63					if (Is_invalidtrap_enabled()) 
     64                                		return(INVALIDEXCEPTION);
     65                                	Set_invalidflag();
     66                                	Sgl_makequietnan(result);
     67					*dstptr = result;
     68					return(NOEXCEPTION);
     69				}
     70				/*
     71			 	 * return infinity
     72			 	 */
     73				Sgl_setinfinity_exponentmantissa(result);
     74				*dstptr = result;
     75				return(NOEXCEPTION);
     76			}
     77		}
     78		else {
     79                	/*
     80                 	 * is NaN; signaling or quiet?
     81                 	 */
     82                	if (Sgl_isone_signaling(opnd1)) {
     83                        	/* trap if INVALIDTRAP enabled */
     84                        	if (Is_invalidtrap_enabled()) 
     85                            		return(INVALIDEXCEPTION);
     86                        	/* make NaN quiet */
     87                        	Set_invalidflag();
     88                        	Sgl_set_quiet(opnd1);
     89                	}
     90			/* 
     91			 * is second operand a signaling NaN? 
     92			 */
     93			else if (Sgl_is_signalingnan(opnd2)) {
     94                        	/* trap if INVALIDTRAP enabled */
     95                        	if (Is_invalidtrap_enabled())
     96                            		return(INVALIDEXCEPTION);
     97                        	/* make NaN quiet */
     98                        	Set_invalidflag();
     99                        	Sgl_set_quiet(opnd2);
    100                		*dstptr = opnd2;
    101                		return(NOEXCEPTION);
    102			}
    103                	/*
    104                 	 * return quiet NaN
    105                 	 */
    106                	*dstptr = opnd1;
    107                	return(NOEXCEPTION);
    108		}
    109	}
    110	/*
    111	 * check second operand for NaN's or infinity
    112	 */
    113	if (Sgl_isinfinity_exponent(opnd2)) {
    114		if (Sgl_iszero_mantissa(opnd2)) {
    115			/*
    116			 * return zero
    117			 */
    118			Sgl_setzero_exponentmantissa(result);
    119			*dstptr = result;
    120			return(NOEXCEPTION);
    121		}
    122                /*
    123                 * is NaN; signaling or quiet?
    124                 */
    125                if (Sgl_isone_signaling(opnd2)) {
    126                        /* trap if INVALIDTRAP enabled */
    127                        if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
    128                        /* make NaN quiet */
    129                        Set_invalidflag();
    130                        Sgl_set_quiet(opnd2);
    131                }
    132                /*
    133                 * return quiet NaN
    134                 */
    135                *dstptr = opnd2;
    136                return(NOEXCEPTION);
    137	}
    138	/*
    139	 * check for division by zero
    140	 */
    141	if (Sgl_iszero_exponentmantissa(opnd2)) {
    142		if (Sgl_iszero_exponentmantissa(opnd1)) {
    143			/* invalid since both operands are zero */
    144			if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION);
    145                        Set_invalidflag();
    146                        Sgl_makequietnan(result);
    147			*dstptr = result;
    148			return(NOEXCEPTION);
    149		}
    150		if (Is_divisionbyzerotrap_enabled())
    151                        return(DIVISIONBYZEROEXCEPTION);
    152                Set_divisionbyzeroflag();
    153                Sgl_setinfinity_exponentmantissa(result);
    154		*dstptr = result;
    155		return(NOEXCEPTION);
    156	}
    157	/*
    158	 * Generate exponent 
    159	 */
    160	dest_exponent = Sgl_exponent(opnd1) - Sgl_exponent(opnd2) + SGL_BIAS;
    161
    162	/*
    163	 * Generate mantissa
    164	 */
    165	if (Sgl_isnotzero_exponent(opnd1)) {
    166		/* set hidden bit */
    167		Sgl_clear_signexponent_set_hidden(opnd1);
    168	}
    169	else {
    170		/* check for zero */
    171		if (Sgl_iszero_mantissa(opnd1)) {
    172			Sgl_setzero_exponentmantissa(result);
    173			*dstptr = result;
    174			return(NOEXCEPTION);
    175		}
    176                /* is denormalized; want to normalize */
    177                Sgl_clear_signexponent(opnd1);
    178                Sgl_leftshiftby1(opnd1);
    179		Sgl_normalize(opnd1,dest_exponent);
    180	}
    181	/* opnd2 needs to have hidden bit set with msb in hidden bit */
    182	if (Sgl_isnotzero_exponent(opnd2)) {
    183		Sgl_clear_signexponent_set_hidden(opnd2);
    184	}
    185	else {
    186                /* is denormalized; want to normalize */
    187                Sgl_clear_signexponent(opnd2);
    188                Sgl_leftshiftby1(opnd2);
    189		while(Sgl_iszero_hiddenhigh7mantissa(opnd2)) {
    190			Sgl_leftshiftby8(opnd2);
    191			dest_exponent += 8;
    192		}
    193		if(Sgl_iszero_hiddenhigh3mantissa(opnd2)) {
    194			Sgl_leftshiftby4(opnd2);
    195			dest_exponent += 4;
    196		}
    197		while(Sgl_iszero_hidden(opnd2)) {
    198			Sgl_leftshiftby1(opnd2);
    199			dest_exponent += 1;
    200		}
    201	}
    202
    203	/* Divide the source mantissas */
    204
    205	/*
    206	 * A non_restoring divide algorithm is used.
    207	 */
    208	Sgl_subtract(opnd1,opnd2,opnd1);
    209	Sgl_setzero(opnd3);
    210	for (count=1;count<=SGL_P && Sgl_all(opnd1);count++) {
    211		Sgl_leftshiftby1(opnd1);
    212		Sgl_leftshiftby1(opnd3);
    213		if (Sgl_iszero_sign(opnd1)) {
    214			Sgl_setone_lowmantissa(opnd3);
    215			Sgl_subtract(opnd1,opnd2,opnd1);
    216		}
    217		else Sgl_addition(opnd1,opnd2,opnd1);
    218	}
    219	if (count <= SGL_P) {
    220		Sgl_leftshiftby1(opnd3);
    221		Sgl_setone_lowmantissa(opnd3);
    222		Sgl_leftshift(opnd3,SGL_P-count);
    223		if (Sgl_iszero_hidden(opnd3)) {
    224			Sgl_leftshiftby1(opnd3);
    225			dest_exponent--;
    226		}
    227	}
    228	else {
    229		if (Sgl_iszero_hidden(opnd3)) {
    230			/* need to get one more bit of result */
    231			Sgl_leftshiftby1(opnd1);
    232			Sgl_leftshiftby1(opnd3);
    233			if (Sgl_iszero_sign(opnd1)) {
    234				Sgl_setone_lowmantissa(opnd3);
    235				Sgl_subtract(opnd1,opnd2,opnd1);
    236			}
    237			else Sgl_addition(opnd1,opnd2,opnd1);
    238			dest_exponent--;
    239		}
    240		if (Sgl_iszero_sign(opnd1)) guardbit = TRUE;
    241		stickybit = Sgl_all(opnd1);
    242	}
    243	inexact = guardbit | stickybit;
    244
    245	/* 
    246	 * round result 
    247	 */
    248	if (inexact && (dest_exponent > 0 || Is_underflowtrap_enabled())) {
    249		Sgl_clear_signexponent(opnd3);
    250		switch (Rounding_mode()) {
    251			case ROUNDPLUS: 
    252				if (Sgl_iszero_sign(result)) 
    253					Sgl_increment_mantissa(opnd3);
    254				break;
    255			case ROUNDMINUS: 
    256				if (Sgl_isone_sign(result)) 
    257					Sgl_increment_mantissa(opnd3);
    258				break;
    259			case ROUNDNEAREST:
    260				if (guardbit) {
    261			   	if (stickybit || Sgl_isone_lowmantissa(opnd3))
    262			      	    Sgl_increment_mantissa(opnd3);
    263				}
    264		}
    265		if (Sgl_isone_hidden(opnd3)) dest_exponent++;
    266	}
    267	Sgl_set_mantissa(result,opnd3);
    268
    269        /* 
    270         * Test for overflow
    271         */
    272	if (dest_exponent >= SGL_INFINITY_EXPONENT) {
    273                /* trap if OVERFLOWTRAP enabled */
    274                if (Is_overflowtrap_enabled()) {
    275                        /*
    276                         * Adjust bias of result
    277                         */
    278                        Sgl_setwrapped_exponent(result,dest_exponent,ovfl);
    279                        *dstptr = result;
    280                        if (inexact) 
    281                            if (Is_inexacttrap_enabled())
    282                                return(OVERFLOWEXCEPTION | INEXACTEXCEPTION);
    283                            else Set_inexactflag();
    284                        return(OVERFLOWEXCEPTION);
    285                }
    286		Set_overflowflag();
    287                /* set result to infinity or largest number */
    288		Sgl_setoverflow(result);
    289		inexact = TRUE;
    290	}
    291        /* 
    292         * Test for underflow
    293         */
    294	else if (dest_exponent <= 0) {
    295                /* trap if UNDERFLOWTRAP enabled */
    296                if (Is_underflowtrap_enabled()) {
    297                        /*
    298                         * Adjust bias of result
    299                         */
    300                        Sgl_setwrapped_exponent(result,dest_exponent,unfl);
    301                        *dstptr = result;
    302                        if (inexact) 
    303                            if (Is_inexacttrap_enabled())
    304                                return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION);
    305                            else Set_inexactflag();
    306                        return(UNDERFLOWEXCEPTION);
    307                }
    308
    309		/* Determine if should set underflow flag */
    310		is_tiny = TRUE;
    311		if (dest_exponent == 0 && inexact) {
    312			switch (Rounding_mode()) {
    313			case ROUNDPLUS: 
    314				if (Sgl_iszero_sign(result)) {
    315					Sgl_increment(opnd3);
    316					if (Sgl_isone_hiddenoverflow(opnd3))
    317                			    is_tiny = FALSE;
    318					Sgl_decrement(opnd3);
    319				}
    320				break;
    321			case ROUNDMINUS: 
    322				if (Sgl_isone_sign(result)) {
    323					Sgl_increment(opnd3);
    324					if (Sgl_isone_hiddenoverflow(opnd3))
    325                			    is_tiny = FALSE;
    326					Sgl_decrement(opnd3);
    327				}
    328				break;
    329			case ROUNDNEAREST:
    330				if (guardbit && (stickybit || 
    331				    Sgl_isone_lowmantissa(opnd3))) {
    332				      	Sgl_increment(opnd3);
    333					if (Sgl_isone_hiddenoverflow(opnd3))
    334                			    is_tiny = FALSE;
    335					Sgl_decrement(opnd3);
    336				}
    337				break;
    338			}
    339		}
    340
    341                /*
    342                 * denormalize result or set to signed zero
    343                 */
    344		stickybit = inexact;
    345		Sgl_denormalize(opnd3,dest_exponent,guardbit,stickybit,inexact);
    346
    347		/* return rounded number */ 
    348		if (inexact) {
    349			switch (Rounding_mode()) {
    350			case ROUNDPLUS:
    351				if (Sgl_iszero_sign(result)) {
    352					Sgl_increment(opnd3);
    353				}
    354				break;
    355			case ROUNDMINUS: 
    356				if (Sgl_isone_sign(result))  {
    357					Sgl_increment(opnd3);
    358				}
    359				break;
    360			case ROUNDNEAREST:
    361				if (guardbit && (stickybit || 
    362				    Sgl_isone_lowmantissa(opnd3))) {
    363			      		Sgl_increment(opnd3);
    364				}
    365				break;
    366			}
    367                	if (is_tiny) Set_underflowflag();
    368                }
    369		Sgl_set_exponentmantissa(result,opnd3);
    370	}
    371	else Sgl_set_exponent(result,dest_exponent);
    372	*dstptr = result;
    373	/* check for inexact */
    374	if (inexact) {
    375		if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION);
    376		else  Set_inexactflag();
    377	}
    378	return(NOEXCEPTION);
    379}