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