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/dfdiv.c $Revision: 1.1 $ 13 * 14 * Purpose: 15 * Double Precision Floating-point Divide 16 * 17 * External Interfaces: 18 * dbl_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 "dbl_float.h" 31 32 /* 33 * Double Precision Floating-point Divide 34 */ 35 36 int 37 dbl_fdiv (dbl_floating_point * srcptr1, dbl_floating_point * srcptr2, 38 dbl_floating_point * dstptr, unsigned int *status) 39 { 40 register unsigned int opnd1p1, opnd1p2, opnd2p1, opnd2p2; 41 register unsigned int opnd3p1, opnd3p2, resultp1, resultp2; 42 register int dest_exponent, count; 43 register boolean inexact = FALSE, guardbit = FALSE, stickybit = FALSE; 44 boolean is_tiny; 45 46 Dbl_copyfromptr(srcptr1,opnd1p1,opnd1p2); 47 Dbl_copyfromptr(srcptr2,opnd2p1,opnd2p2); 48 /* 49 * set sign bit of result 50 */ 51 if (Dbl_sign(opnd1p1) ^ Dbl_sign(opnd2p1)) 52 Dbl_setnegativezerop1(resultp1); 53 else Dbl_setzerop1(resultp1); 54 /* 55 * check first operand for NaN's or infinity 56 */ 57 if (Dbl_isinfinity_exponent(opnd1p1)) { 58 if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { 59 if (Dbl_isnotnan(opnd2p1,opnd2p2)) { 60 if (Dbl_isinfinity(opnd2p1,opnd2p2)) { 61 /* 62 * invalid since both operands 63 * are infinity 64 */ 65 if (Is_invalidtrap_enabled()) 66 return(INVALIDEXCEPTION); 67 Set_invalidflag(); 68 Dbl_makequietnan(resultp1,resultp2); 69 Dbl_copytoptr(resultp1,resultp2,dstptr); 70 return(NOEXCEPTION); 71 } 72 /* 73 * return infinity 74 */ 75 Dbl_setinfinity_exponentmantissa(resultp1,resultp2); 76 Dbl_copytoptr(resultp1,resultp2,dstptr); 77 return(NOEXCEPTION); 78 } 79 } 80 else { 81 /* 82 * is NaN; signaling or quiet? 83 */ 84 if (Dbl_isone_signaling(opnd1p1)) { 85 /* trap if INVALIDTRAP enabled */ 86 if (Is_invalidtrap_enabled()) 87 return(INVALIDEXCEPTION); 88 /* make NaN quiet */ 89 Set_invalidflag(); 90 Dbl_set_quiet(opnd1p1); 91 } 92 /* 93 * is second operand a signaling NaN? 94 */ 95 else if (Dbl_is_signalingnan(opnd2p1)) { 96 /* trap if INVALIDTRAP enabled */ 97 if (Is_invalidtrap_enabled()) 98 return(INVALIDEXCEPTION); 99 /* make NaN quiet */ 100 Set_invalidflag(); 101 Dbl_set_quiet(opnd2p1); 102 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); 103 return(NOEXCEPTION); 104 } 105 /* 106 * return quiet NaN 107 */ 108 Dbl_copytoptr(opnd1p1,opnd1p2,dstptr); 109 return(NOEXCEPTION); 110 } 111 } 112 /* 113 * check second operand for NaN's or infinity 114 */ 115 if (Dbl_isinfinity_exponent(opnd2p1)) { 116 if (Dbl_iszero_mantissa(opnd2p1,opnd2p2)) { 117 /* 118 * return zero 119 */ 120 Dbl_setzero_exponentmantissa(resultp1,resultp2); 121 Dbl_copytoptr(resultp1,resultp2,dstptr); 122 return(NOEXCEPTION); 123 } 124 /* 125 * is NaN; signaling or quiet? 126 */ 127 if (Dbl_isone_signaling(opnd2p1)) { 128 /* trap if INVALIDTRAP enabled */ 129 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); 130 /* make NaN quiet */ 131 Set_invalidflag(); 132 Dbl_set_quiet(opnd2p1); 133 } 134 /* 135 * return quiet NaN 136 */ 137 Dbl_copytoptr(opnd2p1,opnd2p2,dstptr); 138 return(NOEXCEPTION); 139 } 140 /* 141 * check for division by zero 142 */ 143 if (Dbl_iszero_exponentmantissa(opnd2p1,opnd2p2)) { 144 if (Dbl_iszero_exponentmantissa(opnd1p1,opnd1p2)) { 145 /* invalid since both operands are zero */ 146 if (Is_invalidtrap_enabled()) return(INVALIDEXCEPTION); 147 Set_invalidflag(); 148 Dbl_makequietnan(resultp1,resultp2); 149 Dbl_copytoptr(resultp1,resultp2,dstptr); 150 return(NOEXCEPTION); 151 } 152 if (Is_divisionbyzerotrap_enabled()) 153 return(DIVISIONBYZEROEXCEPTION); 154 Set_divisionbyzeroflag(); 155 Dbl_setinfinity_exponentmantissa(resultp1,resultp2); 156 Dbl_copytoptr(resultp1,resultp2,dstptr); 157 return(NOEXCEPTION); 158 } 159 /* 160 * Generate exponent 161 */ 162 dest_exponent = Dbl_exponent(opnd1p1) - Dbl_exponent(opnd2p1) + DBL_BIAS; 163 164 /* 165 * Generate mantissa 166 */ 167 if (Dbl_isnotzero_exponent(opnd1p1)) { 168 /* set hidden bit */ 169 Dbl_clear_signexponent_set_hidden(opnd1p1); 170 } 171 else { 172 /* check for zero */ 173 if (Dbl_iszero_mantissa(opnd1p1,opnd1p2)) { 174 Dbl_setzero_exponentmantissa(resultp1,resultp2); 175 Dbl_copytoptr(resultp1,resultp2,dstptr); 176 return(NOEXCEPTION); 177 } 178 /* is denormalized, want to normalize */ 179 Dbl_clear_signexponent(opnd1p1); 180 Dbl_leftshiftby1(opnd1p1,opnd1p2); 181 Dbl_normalize(opnd1p1,opnd1p2,dest_exponent); 182 } 183 /* opnd2 needs to have hidden bit set with msb in hidden bit */ 184 if (Dbl_isnotzero_exponent(opnd2p1)) { 185 Dbl_clear_signexponent_set_hidden(opnd2p1); 186 } 187 else { 188 /* is denormalized; want to normalize */ 189 Dbl_clear_signexponent(opnd2p1); 190 Dbl_leftshiftby1(opnd2p1,opnd2p2); 191 while (Dbl_iszero_hiddenhigh7mantissa(opnd2p1)) { 192 dest_exponent+=8; 193 Dbl_leftshiftby8(opnd2p1,opnd2p2); 194 } 195 if (Dbl_iszero_hiddenhigh3mantissa(opnd2p1)) { 196 dest_exponent+=4; 197 Dbl_leftshiftby4(opnd2p1,opnd2p2); 198 } 199 while (Dbl_iszero_hidden(opnd2p1)) { 200 dest_exponent++; 201 Dbl_leftshiftby1(opnd2p1,opnd2p2); 202 } 203 } 204 205 /* Divide the source mantissas */ 206 207 /* 208 * A non-restoring divide algorithm is used. 209 */ 210 Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2); 211 Dbl_setzero(opnd3p1,opnd3p2); 212 for (count=1; count <= DBL_P && (opnd1p1 || opnd1p2); count++) { 213 Dbl_leftshiftby1(opnd1p1,opnd1p2); 214 Dbl_leftshiftby1(opnd3p1,opnd3p2); 215 if (Dbl_iszero_sign(opnd1p1)) { 216 Dbl_setone_lowmantissap2(opnd3p2); 217 Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2); 218 } 219 else { 220 Twoword_add(opnd1p1, opnd1p2, opnd2p1, opnd2p2); 221 } 222 } 223 if (count <= DBL_P) { 224 Dbl_leftshiftby1(opnd3p1,opnd3p2); 225 Dbl_setone_lowmantissap2(opnd3p2); 226 Dbl_leftshift(opnd3p1,opnd3p2,(DBL_P-count)); 227 if (Dbl_iszero_hidden(opnd3p1)) { 228 Dbl_leftshiftby1(opnd3p1,opnd3p2); 229 dest_exponent--; 230 } 231 } 232 else { 233 if (Dbl_iszero_hidden(opnd3p1)) { 234 /* need to get one more bit of result */ 235 Dbl_leftshiftby1(opnd1p1,opnd1p2); 236 Dbl_leftshiftby1(opnd3p1,opnd3p2); 237 if (Dbl_iszero_sign(opnd1p1)) { 238 Dbl_setone_lowmantissap2(opnd3p2); 239 Twoword_subtract(opnd1p1,opnd1p2,opnd2p1,opnd2p2); 240 } 241 else { 242 Twoword_add(opnd1p1,opnd1p2,opnd2p1,opnd2p2); 243 } 244 dest_exponent--; 245 } 246 if (Dbl_iszero_sign(opnd1p1)) guardbit = TRUE; 247 stickybit = Dbl_allp1(opnd1p1) || Dbl_allp2(opnd1p2); 248 } 249 inexact = guardbit | stickybit; 250 251 /* 252 * round result 253 */ 254 if (inexact && (dest_exponent > 0 || Is_underflowtrap_enabled())) { 255 Dbl_clear_signexponent(opnd3p1); 256 switch (Rounding_mode()) { 257 case ROUNDPLUS: 258 if (Dbl_iszero_sign(resultp1)) 259 Dbl_increment(opnd3p1,opnd3p2); 260 break; 261 case ROUNDMINUS: 262 if (Dbl_isone_sign(resultp1)) 263 Dbl_increment(opnd3p1,opnd3p2); 264 break; 265 case ROUNDNEAREST: 266 if (guardbit && (stickybit || 267 Dbl_isone_lowmantissap2(opnd3p2))) { 268 Dbl_increment(opnd3p1,opnd3p2); 269 } 270 } 271 if (Dbl_isone_hidden(opnd3p1)) dest_exponent++; 272 } 273 Dbl_set_mantissa(resultp1,resultp2,opnd3p1,opnd3p2); 274 275 /* 276 * Test for overflow 277 */ 278 if (dest_exponent >= DBL_INFINITY_EXPONENT) { 279 /* trap if OVERFLOWTRAP enabled */ 280 if (Is_overflowtrap_enabled()) { 281 /* 282 * Adjust bias of result 283 */ 284 Dbl_setwrapped_exponent(resultp1,dest_exponent,ovfl); 285 Dbl_copytoptr(resultp1,resultp2,dstptr); 286 if (inexact) 287 if (Is_inexacttrap_enabled()) 288 return(OVERFLOWEXCEPTION | INEXACTEXCEPTION); 289 else Set_inexactflag(); 290 return(OVERFLOWEXCEPTION); 291 } 292 Set_overflowflag(); 293 /* set result to infinity or largest number */ 294 Dbl_setoverflow(resultp1,resultp2); 295 inexact = TRUE; 296 } 297 /* 298 * Test for underflow 299 */ 300 else if (dest_exponent <= 0) { 301 /* trap if UNDERFLOWTRAP enabled */ 302 if (Is_underflowtrap_enabled()) { 303 /* 304 * Adjust bias of result 305 */ 306 Dbl_setwrapped_exponent(resultp1,dest_exponent,unfl); 307 Dbl_copytoptr(resultp1,resultp2,dstptr); 308 if (inexact) 309 if (Is_inexacttrap_enabled()) 310 return(UNDERFLOWEXCEPTION | INEXACTEXCEPTION); 311 else Set_inexactflag(); 312 return(UNDERFLOWEXCEPTION); 313 } 314 315 /* Determine if should set underflow flag */ 316 is_tiny = TRUE; 317 if (dest_exponent == 0 && inexact) { 318 switch (Rounding_mode()) { 319 case ROUNDPLUS: 320 if (Dbl_iszero_sign(resultp1)) { 321 Dbl_increment(opnd3p1,opnd3p2); 322 if (Dbl_isone_hiddenoverflow(opnd3p1)) 323 is_tiny = FALSE; 324 Dbl_decrement(opnd3p1,opnd3p2); 325 } 326 break; 327 case ROUNDMINUS: 328 if (Dbl_isone_sign(resultp1)) { 329 Dbl_increment(opnd3p1,opnd3p2); 330 if (Dbl_isone_hiddenoverflow(opnd3p1)) 331 is_tiny = FALSE; 332 Dbl_decrement(opnd3p1,opnd3p2); 333 } 334 break; 335 case ROUNDNEAREST: 336 if (guardbit && (stickybit || 337 Dbl_isone_lowmantissap2(opnd3p2))) { 338 Dbl_increment(opnd3p1,opnd3p2); 339 if (Dbl_isone_hiddenoverflow(opnd3p1)) 340 is_tiny = FALSE; 341 Dbl_decrement(opnd3p1,opnd3p2); 342 } 343 break; 344 } 345 } 346 347 /* 348 * denormalize result or set to signed zero 349 */ 350 stickybit = inexact; 351 Dbl_denormalize(opnd3p1,opnd3p2,dest_exponent,guardbit, 352 stickybit,inexact); 353 354 /* return rounded number */ 355 if (inexact) { 356 switch (Rounding_mode()) { 357 case ROUNDPLUS: 358 if (Dbl_iszero_sign(resultp1)) { 359 Dbl_increment(opnd3p1,opnd3p2); 360 } 361 break; 362 case ROUNDMINUS: 363 if (Dbl_isone_sign(resultp1)) { 364 Dbl_increment(opnd3p1,opnd3p2); 365 } 366 break; 367 case ROUNDNEAREST: 368 if (guardbit && (stickybit || 369 Dbl_isone_lowmantissap2(opnd3p2))) { 370 Dbl_increment(opnd3p1,opnd3p2); 371 } 372 break; 373 } 374 if (is_tiny) Set_underflowflag(); 375 } 376 Dbl_set_exponentmantissa(resultp1,resultp2,opnd3p1,opnd3p2); 377 } 378 else Dbl_set_exponent(resultp1,dest_exponent); 379 Dbl_copytoptr(resultp1,resultp2,dstptr); 380 381 /* check for inexact */ 382 if (inexact) { 383 if (Is_inexacttrap_enabled()) return(INEXACTEXCEPTION); 384 else Set_inexactflag(); 385 } 386 return(NOEXCEPTION); 387 } 388
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.