1206917Smarius 2206917Smarius/* 3206917Smarius=============================================================================== 4206917Smarius 5206917SmariusThis C source file is part of TestFloat, Release 2a, a package of programs 6206917Smariusfor testing the correctness of floating-point arithmetic complying to the 7206917SmariusIEC/IEEE Standard for Floating-Point. 8206917Smarius 9206917SmariusWritten by John R. Hauser. More information is available through the Web 10206917Smariuspage `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/TestFloat.html'. 11206917Smarius 12206917SmariusTHIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort 13206917Smariushas been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT 14206917SmariusTIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO 15206917SmariusPERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY 16206917SmariusAND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE. 17206917Smarius 18206917SmariusDerivative works are acceptable, even for commercial purposes, so long as 19206917Smarius(1) they include prominent notice that the work is derivative, and (2) they 20206917Smariusinclude prominent notice akin to these four paragraphs for those parts of 21206917Smariusthis code that are retained. 22206917Smarius 23206917Smarius=============================================================================== 24206917Smarius*/ 25206917Smarius 26206917Smariusint8 slow_float_rounding_mode; 27206917Smariusint8 slow_float_exception_flags; 28206917Smariusint8 slow_float_detect_tininess; 29206917Smarius 30206917Smariustypedef struct { 31206917Smarius bits32 a0, a1; 32206917Smarius} bits64X; 33206917Smarius 34206917Smariustypedef struct { 35206917Smarius flag isNaN; 36206917Smarius flag isInf; 37206917Smarius flag isZero; 38206917Smarius flag sign; 39206917Smarius int16 exp; 40206917Smarius bits64X sig; 41206917Smarius} floatX; 42206917Smarius 43206917Smariusstatic const floatX floatXNaN = { TRUE, FALSE, FALSE, FALSE, 0, { 0, 0 } }; 44206917Smariusstatic const floatX floatXPositiveZero = 45206917Smarius { FALSE, FALSE, TRUE, FALSE, 0, { 0, 0 } }; 46206917Smariusstatic const floatX floatXNegativeZero = 47206917Smarius { FALSE, FALSE, TRUE, TRUE, 0, { 0, 0 } }; 48206917Smarius 49206917Smariusstatic bits64X shortShift64Left( bits64X a, int8 shiftCount ) 50206917Smarius{ 51206917Smarius int8 negShiftCount; 52206917Smarius 53206917Smarius negShiftCount = ( - shiftCount & 31 ); 54206917Smarius a.a0 = ( a.a0<<shiftCount ) | ( a.a1>>negShiftCount ); 55206917Smarius a.a1 <<= shiftCount; 56206917Smarius return a; 57206917Smarius 58206917Smarius} 59206917Smarius 60206917Smariusstatic bits64X shortShift64RightJamming( bits64X a, int8 shiftCount ) 61206917Smarius{ 62206917Smarius int8 negShiftCount; 63206917Smarius bits32 extra; 64206917Smarius 65206917Smarius negShiftCount = ( - shiftCount & 31 ); 66206917Smarius extra = a.a1<<negShiftCount; 67206917Smarius a.a1 = ( a.a0<<negShiftCount ) | ( a.a1>>shiftCount ) | ( extra != 0 ); 68206917Smarius a.a0 >>= shiftCount; 69206917Smarius return a; 70206917Smarius 71206917Smarius} 72206917Smarius 73206917Smariusstatic bits64X neg64( bits64X a ) 74206917Smarius{ 75206917Smarius 76206917Smarius if ( a.a1 == 0 ) { 77206917Smarius a.a0 = - a.a0; 78206917Smarius } 79206917Smarius else { 80206917Smarius a.a1 = - a.a1; 81206917Smarius a.a0 = ~ a.a0; 82206917Smarius } 83206917Smarius return a; 84206917Smarius 85206917Smarius} 86206917Smarius 87206917Smariusstatic bits64X add64( bits64X a, bits64X b ) 88206917Smarius{ 89206917Smarius 90206917Smarius a.a1 += b.a1; 91206917Smarius a.a0 += b.a0 + ( a.a1 < b.a1 ); 92206917Smarius return a; 93206917Smarius 94206917Smarius} 95206917Smarius 96206917Smariusstatic flag eq64( bits64X a, bits64X b ) 97206917Smarius{ 98206917Smarius 99206917Smarius return ( a.a0 == b.a0 ) && ( a.a1 == b.a1 ); 100206917Smarius 101206917Smarius} 102206917Smarius 103206917Smariusstatic flag le64( bits64X a, bits64X b ) 104206917Smarius{ 105206917Smarius 106206917Smarius return ( a.a0 < b.a0 ) || ( ( a.a0 == b.a0 ) && ( a.a1 <= b.a1 ) ); 107206917Smarius 108206917Smarius} 109206917Smarius 110206917Smariusstatic flag lt64( bits64X a, bits64X b ) 111206917Smarius{ 112206917Smarius 113206917Smarius return ( a.a0 < b.a0 ) || ( ( a.a0 == b.a0 ) && ( a.a1 < b.a1 ) ); 114206917Smarius 115206917Smarius} 116206917Smarius 117206917Smariusstatic floatX roundFloatXTo24( flag isTiny, floatX zx ) 118206917Smarius{ 119206917Smarius 120206917Smarius if ( zx.sig.a1 ) { 121206917Smarius slow_float_exception_flags |= float_flag_inexact; 122206917Smarius if ( isTiny ) slow_float_exception_flags |= float_flag_underflow; 123206917Smarius switch ( slow_float_rounding_mode ) { 124206917Smarius case float_round_nearest_even: 125206917Smarius if ( zx.sig.a1 < 0x80000000 ) goto noIncrement; 126206917Smarius if ( ( zx.sig.a1 == 0x80000000 ) && ! ( zx.sig.a0 & 1 ) ) { 127206917Smarius goto noIncrement; 128206917Smarius } 129206917Smarius break; 130206917Smarius case float_round_to_zero: 131206917Smarius goto noIncrement; 132206917Smarius case float_round_down: 133206917Smarius if ( ! zx.sign ) goto noIncrement; 134206917Smarius break; 135206917Smarius case float_round_up: 136206917Smarius if ( zx.sign ) goto noIncrement; 137206917Smarius break; 138206917Smarius } 139206917Smarius ++zx.sig.a0; 140206917Smarius if ( zx.sig.a0 == 0x01000000 ) { 141206917Smarius zx.sig.a0 = 0x00800000; 142206917Smarius ++zx.exp; 143206917Smarius } 144206917Smarius } 145206917Smarius noIncrement: 146206917Smarius zx.sig.a1 = 0; 147206917Smarius return zx; 148206917Smarius 149206917Smarius} 150206917Smarius 151206917Smariusstatic floatX roundFloatXTo53( flag isTiny, floatX zx ) 152206917Smarius{ 153206917Smarius int8 roundBits; 154206917Smarius 155206917Smarius roundBits = zx.sig.a1 & 7; 156206917Smarius zx.sig.a1 -= roundBits; 157206917Smarius if ( roundBits ) { 158206917Smarius slow_float_exception_flags |= float_flag_inexact; 159206917Smarius if ( isTiny ) slow_float_exception_flags |= float_flag_underflow; 160206917Smarius switch ( slow_float_rounding_mode ) { 161206917Smarius case float_round_nearest_even: 162206917Smarius if ( roundBits < 4 ) goto noIncrement; 163206917Smarius if ( ( roundBits == 4 ) && ! ( zx.sig.a1 & 8 ) ) goto noIncrement; 164206917Smarius break; 165206917Smarius case float_round_to_zero: 166206917Smarius goto noIncrement; 167206917Smarius case float_round_down: 168206917Smarius if ( ! zx.sign ) goto noIncrement; 169206917Smarius break; 170206917Smarius case float_round_up: 171206917Smarius if ( zx.sign ) goto noIncrement; 172206917Smarius break; 173206917Smarius } 174206917Smarius zx.sig.a1 += 8; 175206917Smarius zx.sig.a0 += ( zx.sig.a1 == 0 ); 176206917Smarius if ( zx.sig.a0 == 0x01000000 ) { 177206917Smarius zx.sig.a0 = 0x00800000; 178206917Smarius ++zx.exp; 179206917Smarius } 180206917Smarius } 181206917Smarius noIncrement: 182206917Smarius return zx; 183206917Smarius 184206917Smarius} 185206917Smarius 186206917Smariusstatic floatX int32ToFloatX( int32 a ) 187206917Smarius{ 188206917Smarius floatX ax; 189206917Smarius 190206917Smarius ax.isNaN = FALSE; 191206917Smarius ax.isInf = FALSE; 192206917Smarius ax.sign = ( a < 0 ); 193206917Smarius ax.sig.a1 = ax.sign ? - a : a; 194206917Smarius ax.sig.a0 = 0; 195206917Smarius if ( a == 0 ) { 196206917Smarius ax.isZero = TRUE; 197206917Smarius return ax; 198206917Smarius } 199206917Smarius ax.isZero = FALSE; 200206917Smarius ax.sig = shortShift64Left( ax.sig, 23 ); 201206917Smarius ax.exp = 32; 202206917Smarius while ( ax.sig.a0 < 0x00800000 ) { 203206917Smarius ax.sig = shortShift64Left( ax.sig, 1 ); 204206917Smarius --ax.exp; 205206917Smarius } 206206917Smarius return ax; 207206917Smarius 208206917Smarius} 209206917Smarius 210206917Smariusstatic int32 floatXToInt32( floatX ax ) 211206917Smarius{ 212206917Smarius int8 savedExceptionFlags; 213206917Smarius int16 shiftCount; 214206917Smarius int32 z; 215206917Smarius 216206917Smarius if ( ax.isInf || ax.isNaN ) { 217206917Smarius slow_float_exception_flags |= float_flag_invalid; 218206917Smarius return ( ax.isInf & ax.sign ) ? 0x80000000 : 0x7FFFFFFF; 219206917Smarius } 220206917Smarius if ( ax.isZero ) return 0; 221206917Smarius savedExceptionFlags = slow_float_exception_flags; 222206917Smarius shiftCount = 52 - ax.exp; 223206917Smarius if ( 56 < shiftCount ) { 224206917Smarius ax.sig.a1 = 1; 225206917Smarius ax.sig.a0 = 0; 226206917Smarius } 227206917Smarius else { 228206917Smarius while ( 0 < shiftCount ) { 229206917Smarius ax.sig = shortShift64RightJamming( ax.sig, 1 ); 230206917Smarius --shiftCount; 231206917Smarius } 232206917Smarius } 233206917Smarius ax = roundFloatXTo53( FALSE, ax ); 234206917Smarius ax.sig = shortShift64RightJamming( ax.sig, 3 ); 235206917Smarius z = ax.sig.a1; 236206917Smarius if ( ax.sign ) z = - z; 237206917Smarius if ( ( shiftCount < 0 ) 238206917Smarius || ax.sig.a0 239206917Smarius || ( ( z != 0 ) && ( ( ax.sign ^ ( z < 0 ) ) != 0 ) ) 240206917Smarius ) { 241206917Smarius slow_float_exception_flags = savedExceptionFlags | float_flag_invalid; 242206917Smarius return ax.sign ? 0x80000000 : 0x7FFFFFFF; 243206917Smarius } 244206917Smarius return z; 245206917Smarius 246206917Smarius} 247206917Smarius 248206917Smariusstatic floatX float32ToFloatX( float32 a ) 249206917Smarius{ 250206917Smarius int16 expField; 251206917Smarius floatX ax; 252206917Smarius 253206917Smarius ax.isNaN = FALSE; 254206917Smarius ax.isInf = FALSE; 255206917Smarius ax.isZero = FALSE; 256206917Smarius ax.sign = ( ( a & 0x80000000 ) != 0 ); 257206917Smarius expField = ( a>>23 ) & 0xFF; 258206917Smarius ax.sig.a1 = 0; 259206917Smarius ax.sig.a0 = a & 0x007FFFFF; 260206917Smarius if ( expField == 0 ) { 261206917Smarius if ( ax.sig.a0 == 0 ) { 262206917Smarius ax.isZero = TRUE; 263206917Smarius } 264206917Smarius else { 265206917Smarius expField = 1 - 0x7F; 266206917Smarius do { 267206917Smarius ax.sig.a0 <<= 1; 268206917Smarius --expField; 269206917Smarius } while ( ax.sig.a0 < 0x00800000 ); 270206917Smarius ax.exp = expField; 271206917Smarius } 272206917Smarius } 273206917Smarius else if ( expField == 0xFF ) { 274206917Smarius if ( ax.sig.a0 == 0 ) { 275206917Smarius ax.isInf = TRUE; 276206917Smarius } 277206917Smarius else { 278206917Smarius ax.isNaN = TRUE; 279206917Smarius } 280206917Smarius } 281206917Smarius else { 282206917Smarius ax.sig.a0 |= 0x00800000; 283206917Smarius ax.exp = expField - 0x7F; 284206917Smarius } 285206917Smarius return ax; 286206917Smarius 287206917Smarius} 288206917Smarius 289206917Smariusstatic float32 floatXToFloat32( floatX zx ) 290206917Smarius{ 291206917Smarius floatX savedZ; 292206917Smarius flag isTiny; 293206917Smarius int16 expField; 294206917Smarius float32 z; 295206917Smarius 296206917Smarius if ( zx.isZero ) return zx.sign ? 0x80000000 : 0; 297206917Smarius if ( zx.isInf ) return zx.sign ? 0xFF800000 : 0x7F800000; 298206917Smarius if ( zx.isNaN ) return 0xFFFFFFFF; 299206917Smarius while ( 0x01000000 <= zx.sig.a0 ) { 300206917Smarius zx.sig = shortShift64RightJamming( zx.sig, 1 ); 301206917Smarius ++zx.exp; 302206917Smarius } 303206917Smarius while ( zx.sig.a0 < 0x00800000 ) { 304206917Smarius zx.sig = shortShift64Left( zx.sig, 1 ); 305206917Smarius --zx.exp; 306206917Smarius } 307206917Smarius savedZ = zx; 308206917Smarius isTiny = 309206917Smarius ( slow_float_detect_tininess == float_tininess_before_rounding ) 310206917Smarius && ( zx.exp + 0x7F <= 0 ); 311206917Smarius zx = roundFloatXTo24( isTiny, zx ); 312206917Smarius expField = zx.exp + 0x7F; 313206917Smarius if ( 0xFF <= expField ) { 314206917Smarius slow_float_exception_flags |= 315206917Smarius float_flag_overflow | float_flag_inexact; 316206917Smarius if ( zx.sign ) { 317206917Smarius switch ( slow_float_rounding_mode ) { 318206917Smarius case float_round_nearest_even: 319206917Smarius case float_round_down: 320206917Smarius z = 0xFF800000; 321206917Smarius break; 322206917Smarius case float_round_to_zero: 323206917Smarius case float_round_up: 324206917Smarius z = 0xFF7FFFFF; 325206917Smarius break; 326206917Smarius } 327206917Smarius } 328206917Smarius else { 329206917Smarius switch ( slow_float_rounding_mode ) { 330206917Smarius case float_round_nearest_even: 331206917Smarius case float_round_up: 332206917Smarius z = 0x7F800000; 333206917Smarius break; 334206917Smarius case float_round_to_zero: 335206917Smarius case float_round_down: 336206917Smarius z = 0x7F7FFFFF; 337206917Smarius break; 338206917Smarius } 339206917Smarius } 340206917Smarius return z; 341206917Smarius } 342206917Smarius if ( expField <= 0 ) { 343206917Smarius isTiny = TRUE; 344206917Smarius zx = savedZ; 345206917Smarius expField = zx.exp + 0x7F; 346206917Smarius if ( expField < -27 ) { 347206917Smarius zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 ); 348206917Smarius zx.sig.a0 = 0; 349206917Smarius } 350206917Smarius else { 351206917Smarius while ( expField <= 0 ) { 352206917Smarius zx.sig = shortShift64RightJamming( zx.sig, 1 ); 353206917Smarius ++expField; 354206917Smarius } 355206917Smarius } 356206917Smarius zx = roundFloatXTo24( isTiny, zx ); 357206917Smarius expField = ( 0x00800000 <= zx.sig.a0 ) ? 1 : 0; 358206917Smarius } 359206917Smarius z = expField; 360206917Smarius z <<= 23; 361206917Smarius if ( zx.sign ) z |= 0x80000000; 362206917Smarius z |= zx.sig.a0 & 0x007FFFFF; 363206917Smarius return z; 364206917Smarius 365206917Smarius} 366206917Smarius 367206917Smariusstatic floatX float64ToFloatX( float64 a ) 368206917Smarius{ 369206917Smarius int16 expField; 370206917Smarius floatX ax; 371206917Smarius 372206917Smarius ax.isNaN = FALSE; 373206917Smarius ax.isInf = FALSE; 374206917Smarius ax.isZero = FALSE; 375206917Smarius#ifdef BITS64 376206917Smarius ax.sign = ( ( a & LIT64( 0x8000000000000000 ) ) != 0 ); 377206917Smarius expField = ( a>>52 ) & 0x7FF; 378206917Smarius ax.sig.a1 = a; 379206917Smarius ax.sig.a0 = ( a>>32 ) & 0x000FFFFF; 380206917Smarius#else 381206917Smarius ax.sign = ( ( a.high & 0x80000000 ) != 0 ); 382206917Smarius expField = ( a.high>>( 52 - 32 ) ) & 0x7FF; 383206917Smarius ax.sig.a1 = a.low; 384206917Smarius ax.sig.a0 = a.high & 0x000FFFFF; 385206917Smarius#endif 386206917Smarius if ( expField == 0 ) { 387206917Smarius if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) { 388206917Smarius ax.isZero = TRUE; 389206917Smarius } 390206917Smarius else { 391206917Smarius expField = 1 - 0x3FF; 392206917Smarius do { 393206917Smarius ax.sig = shortShift64Left( ax.sig, 1 ); 394206917Smarius --expField; 395206917Smarius } while ( ax.sig.a0 < 0x00100000 ); 396206917Smarius ax.exp = expField; 397206917Smarius } 398206917Smarius } 399206917Smarius else if ( expField == 0x7FF ) { 400206917Smarius if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) { 401206917Smarius ax.isInf = TRUE; 402206917Smarius } 403206917Smarius else { 404206917Smarius ax.isNaN = TRUE; 405206917Smarius } 406206917Smarius } 407206917Smarius else { 408206917Smarius ax.exp = expField - 0x3FF; 409206917Smarius ax.sig.a0 |= 0x00100000; 410206917Smarius } 411206917Smarius ax.sig = shortShift64Left( ax.sig, 3 ); 412206917Smarius return ax; 413206917Smarius 414206917Smarius} 415206917Smarius 416206917Smariusstatic float64 floatXToFloat64( floatX zx ) 417206917Smarius{ 418206917Smarius floatX savedZ; 419206917Smarius flag isTiny; 420206917Smarius int16 expField; 421206917Smarius float64 z; 422206917Smarius 423206917Smarius#ifdef BITS64 424206917Smarius if ( zx.isZero ) return zx.sign ? LIT64( 0x8000000000000000 ) : 0; 425206917Smarius if ( zx.isInf ) { 426206917Smarius return 427206917Smarius zx.sign ? LIT64( 0xFFF0000000000000 ) 428206917Smarius : LIT64( 0x7FF0000000000000 ); 429206917Smarius } 430206917Smarius if ( zx.isNaN ) return LIT64( 0xFFFFFFFFFFFFFFFF ); 431206917Smarius#else 432206917Smarius if ( zx.isZero ) { 433206917Smarius z.low = 0; 434206917Smarius z.high = zx.sign ? 0x80000000 : 0; 435206917Smarius return z; 436206917Smarius } 437206917Smarius if ( zx.isInf ) { 438206917Smarius z.low = 0; 439206917Smarius z.high = zx.sign ? 0xFFF00000 : 0x7FF00000; 440206917Smarius return z; 441206917Smarius } 442206917Smarius if ( zx.isNaN ) { 443206917Smarius z.high = z.low = 0xFFFFFFFF; 444206917Smarius return z; 445206917Smarius } 446206917Smarius#endif 447206917Smarius while ( 0x01000000 <= zx.sig.a0 ) { 448206917Smarius zx.sig = shortShift64RightJamming( zx.sig, 1 ); 449206917Smarius ++zx.exp; 450206917Smarius } 451206917Smarius while ( zx.sig.a0 < 0x00800000 ) { 452206917Smarius zx.sig = shortShift64Left( zx.sig, 1 ); 453206917Smarius --zx.exp; 454206917Smarius } 455206917Smarius savedZ = zx; 456206917Smarius isTiny = 457206917Smarius ( slow_float_detect_tininess == float_tininess_before_rounding ) 458206917Smarius && ( zx.exp + 0x3FF <= 0 ); 459206917Smarius zx = roundFloatXTo53( isTiny, zx ); 460206917Smarius expField = zx.exp + 0x3FF; 461206917Smarius if ( 0x7FF <= expField ) { 462206917Smarius slow_float_exception_flags |= 463206917Smarius float_flag_overflow | float_flag_inexact; 464206917Smarius#ifdef BITS64 465206917Smarius if ( zx.sign ) { 466206917Smarius switch ( slow_float_rounding_mode ) { 467206917Smarius case float_round_nearest_even: 468206917Smarius case float_round_down: 469206917Smarius z = LIT64( 0xFFF0000000000000 ); 470206917Smarius break; 471206917Smarius case float_round_to_zero: 472206917Smarius case float_round_up: 473206917Smarius z = LIT64( 0xFFEFFFFFFFFFFFFF ); 474206917Smarius break; 475206917Smarius } 476206917Smarius } 477206917Smarius else { 478206917Smarius switch ( slow_float_rounding_mode ) { 479206917Smarius case float_round_nearest_even: 480206917Smarius case float_round_up: 481206917Smarius z = LIT64( 0x7FF0000000000000 ); 482206917Smarius break; 483206917Smarius case float_round_to_zero: 484206917Smarius case float_round_down: 485206917Smarius z = LIT64( 0x7FEFFFFFFFFFFFFF ); 486206917Smarius break; 487206917Smarius } 488206917Smarius } 489206917Smarius#else 490206917Smarius if ( zx.sign ) { 491206917Smarius switch ( slow_float_rounding_mode ) { 492206917Smarius case float_round_nearest_even: 493206917Smarius case float_round_down: 494206917Smarius z.low = 0; 495206917Smarius z.high = 0xFFF00000; 496206917Smarius break; 497206917Smarius case float_round_to_zero: 498206917Smarius case float_round_up: 499206917Smarius z.low = 0xFFFFFFFF; 500206917Smarius z.high = 0xFFEFFFFF; 501206917Smarius break; 502206917Smarius } 503206917Smarius } 504206917Smarius else { 505206917Smarius switch ( slow_float_rounding_mode ) { 506206917Smarius case float_round_nearest_even: 507206917Smarius case float_round_up: 508206917Smarius z.low = 0; 509206917Smarius z.high = 0x7FF00000; 510206917Smarius break; 511206917Smarius case float_round_to_zero: 512206917Smarius case float_round_down: 513206917Smarius z.low = 0xFFFFFFFF; 514206917Smarius z.high = 0x7FEFFFFF; 515206917Smarius break; 516206917Smarius } 517206917Smarius } 518206917Smarius#endif 519206917Smarius return z; 520206917Smarius } 521206917Smarius if ( expField <= 0 ) { 522206917Smarius isTiny = TRUE; 523206917Smarius zx = savedZ; 524206917Smarius expField = zx.exp + 0x3FF; 525206917Smarius if ( expField < -56 ) { 526206917Smarius zx.sig.a1 = ( zx.sig.a0 != 0 ) || ( zx.sig.a1 != 0 ); 527206917Smarius zx.sig.a0 = 0; 528206917Smarius } 529206917Smarius else { 530206917Smarius while ( expField <= 0 ) { 531206917Smarius zx.sig = shortShift64RightJamming( zx.sig, 1 ); 532206917Smarius ++expField; 533206917Smarius } 534206917Smarius } 535206917Smarius zx = roundFloatXTo53( isTiny, zx ); 536206917Smarius expField = ( 0x00800000 <= zx.sig.a0 ) ? 1 : 0; 537206917Smarius } 538206917Smarius zx.sig = shortShift64RightJamming( zx.sig, 3 ); 539206917Smarius#ifdef BITS64 540206917Smarius z = expField; 541206917Smarius z <<= 52; 542206917Smarius if ( zx.sign ) z |= LIT64( 0x8000000000000000 ); 543206917Smarius z |= ( ( (bits64) ( zx.sig.a0 & 0x000FFFFF ) )<<32 ) | zx.sig.a1; 544206917Smarius#else 545206917Smarius z.low = zx.sig.a1; 546206917Smarius z.high = expField; 547206917Smarius z.high <<= 52 - 32; 548206917Smarius if ( zx.sign ) z.high |= 0x80000000; 549206917Smarius z.high |= zx.sig.a0 & 0x000FFFFF; 550206917Smarius#endif 551206917Smarius return z; 552206917Smarius 553206917Smarius} 554206917Smarius 555206917Smariusstatic floatX floatXInvalid( void ) 556206917Smarius{ 557206917Smarius 558206917Smarius slow_float_exception_flags |= float_flag_invalid; 559206917Smarius return floatXNaN; 560206917Smarius 561206917Smarius} 562206917Smarius 563206917Smariusstatic floatX floatXRoundToInt( floatX ax ) 564206917Smarius{ 565206917Smarius int16 shiftCount, i; 566206917Smarius 567206917Smarius if ( ax.isNaN || ax.isInf ) return ax; 568206917Smarius shiftCount = 52 - ax.exp; 569206917Smarius if ( shiftCount <= 0 ) return ax; 570206917Smarius if ( 55 < shiftCount ) { 571206917Smarius ax.exp = 52; 572206917Smarius ax.sig.a1 = ! ax.isZero; 573206917Smarius ax.sig.a0 = 0; 574206917Smarius } 575206917Smarius else { 576206917Smarius while ( 0 < shiftCount ) { 577206917Smarius ax.sig = shortShift64RightJamming( ax.sig, 1 ); 578206917Smarius ++ax.exp; 579206917Smarius --shiftCount; 580206917Smarius } 581206917Smarius } 582206917Smarius ax = roundFloatXTo53( FALSE, ax ); 583206917Smarius if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) ax.isZero = TRUE; 584206917Smarius return ax; 585206917Smarius 586206917Smarius} 587206917Smarius 588206917Smariusstatic floatX floatXAdd( floatX ax, floatX bx ) 589206917Smarius{ 590206917Smarius int16 expDiff; 591206917Smarius floatX zx; 592206917Smarius 593206917Smarius if ( ax.isNaN ) return ax; 594206917Smarius if ( bx.isNaN ) return bx; 595206917Smarius if ( ax.isInf && bx.isInf ) { 596206917Smarius if ( ax.sign == bx.sign ) return ax; 597206917Smarius return floatXInvalid(); 598206917Smarius } 599206917Smarius if ( ax.isInf ) return ax; 600206917Smarius if ( bx.isInf ) return bx; 601206917Smarius if ( ax.isZero && bx.isZero ) { 602206917Smarius if ( ax.sign == bx.sign ) return ax; 603206917Smarius goto completeCancellation; 604206917Smarius } 605206917Smarius if ( ( ax.sign != bx.sign ) 606206917Smarius && ( ax.exp == bx.exp ) 607206917Smarius && eq64( ax.sig, bx.sig ) 608206917Smarius ) { 609206917Smarius completeCancellation: 610206917Smarius return 611206917Smarius ( slow_float_rounding_mode == float_round_down ) ? 612206917Smarius floatXNegativeZero 613206917Smarius : floatXPositiveZero; 614206917Smarius } 615206917Smarius if ( ax.isZero ) return bx; 616206917Smarius if ( bx.isZero ) return ax; 617206917Smarius expDiff = ax.exp - bx.exp; 618206917Smarius if ( expDiff < 0 ) { 619206917Smarius zx = ax; 620206917Smarius zx.exp = bx.exp; 621206917Smarius if ( expDiff < -56 ) { 622206917Smarius zx.sig.a1 = 1; 623206917Smarius zx.sig.a0 = 0; 624206917Smarius } 625206917Smarius else { 626206917Smarius while ( expDiff < 0 ) { 627206917Smarius zx.sig = shortShift64RightJamming( zx.sig, 1 ); 628206917Smarius ++expDiff; 629206917Smarius } 630206917Smarius } 631206917Smarius if ( ax.sign != bx.sign ) zx.sig = neg64( zx.sig ); 632206917Smarius zx.sign = bx.sign; 633206917Smarius zx.sig = add64( zx.sig, bx.sig ); 634206917Smarius } 635206917Smarius else { 636206917Smarius zx = bx; 637206917Smarius zx.exp = ax.exp; 638206917Smarius if ( 56 < expDiff ) { 639206917Smarius zx.sig.a1 = 1; 640206917Smarius zx.sig.a0 = 0; 641206917Smarius } 642206917Smarius else { 643206917Smarius while ( 0 < expDiff ) { 644206917Smarius zx.sig = shortShift64RightJamming( zx.sig, 1 ); 645206917Smarius --expDiff; 646206917Smarius } 647206917Smarius } 648206917Smarius if ( ax.sign != bx.sign ) zx.sig = neg64( zx.sig ); 649206917Smarius zx.sign = ax.sign; 650206917Smarius zx.sig = add64( zx.sig, ax.sig ); 651206917Smarius } 652206917Smarius if ( zx.sig.a0 & 0x80000000 ) { 653206917Smarius zx.sig = neg64( zx.sig ); 654206917Smarius zx.sign = ! zx.sign; 655206917Smarius } 656206917Smarius return zx; 657206917Smarius 658206917Smarius} 659206917Smarius 660206917Smariusstatic floatX floatXMul( floatX ax, floatX bx ) 661206917Smarius{ 662206917Smarius int8 bitNum; 663206917Smarius floatX zx; 664206917Smarius 665206917Smarius if ( ax.isNaN ) return ax; 666206917Smarius if ( bx.isNaN ) return bx; 667206917Smarius if ( ax.isInf ) { 668206917Smarius if ( bx.isZero ) return floatXInvalid(); 669206917Smarius if ( bx.sign ) ax.sign = ! ax.sign; 670206917Smarius return ax; 671206917Smarius } 672206917Smarius if ( bx.isInf ) { 673206917Smarius if ( ax.isZero ) return floatXInvalid(); 674206917Smarius if ( ax.sign ) bx.sign = ! bx.sign; 675206917Smarius return bx; 676206917Smarius } 677206917Smarius zx = ax; 678206917Smarius zx.sign ^= bx.sign; 679206917Smarius if ( ax.isZero || bx.isZero ) { 680206917Smarius return zx.sign ? floatXNegativeZero : floatXPositiveZero; 681206917Smarius } 682206917Smarius zx.exp += bx.exp + 1; 683206917Smarius zx.sig.a1 = 0; 684206917Smarius zx.sig.a0 = 0; 685206917Smarius for ( bitNum = 0; bitNum < 55; ++bitNum ) { 686206917Smarius if ( bx.sig.a1 & 2 ) zx.sig = add64( zx.sig, ax.sig ); 687206917Smarius bx.sig = shortShift64RightJamming( bx.sig, 1 ); 688206917Smarius zx.sig = shortShift64RightJamming( zx.sig, 1 ); 689206917Smarius } 690206917Smarius return zx; 691206917Smarius 692206917Smarius} 693206917Smarius 694206917Smariusstatic floatX floatXDiv( floatX ax, floatX bx ) 695206917Smarius{ 696206917Smarius bits64X negBSig; 697206917Smarius int8 bitNum; 698206917Smarius floatX zx; 699206917Smarius 700206917Smarius if ( ax.isNaN ) return ax; 701206917Smarius if ( bx.isNaN ) return bx; 702206917Smarius if ( ax.isInf ) { 703206917Smarius if ( bx.isInf ) return floatXInvalid(); 704206917Smarius if ( bx.sign ) ax.sign = ! ax.sign; 705206917Smarius return ax; 706206917Smarius } 707206917Smarius if ( bx.isZero ) { 708206917Smarius if ( ax.isZero ) return floatXInvalid(); 709206917Smarius slow_float_exception_flags |= float_flag_divbyzero; 710206917Smarius if ( ax.sign ) bx.sign = ! bx.sign; 711206917Smarius bx.isZero = FALSE; 712206917Smarius bx.isInf = TRUE; 713206917Smarius return bx; 714206917Smarius } 715206917Smarius zx = ax; 716206917Smarius zx.sign ^= bx.sign; 717206917Smarius if ( ax.isZero || bx.isInf ) { 718206917Smarius return zx.sign ? floatXNegativeZero : floatXPositiveZero; 719206917Smarius } 720206917Smarius zx.exp -= bx.exp + 1; 721206917Smarius zx.sig.a1 = 0; 722206917Smarius zx.sig.a0 = 0; 723206917Smarius negBSig = neg64( bx.sig ); 724206917Smarius for ( bitNum = 0; bitNum < 56; ++bitNum ) { 725206917Smarius if ( le64( bx.sig, ax.sig ) ) { 726206917Smarius zx.sig.a1 |= 1; 727206917Smarius ax.sig = add64( ax.sig, negBSig ); 728206917Smarius } 729206917Smarius ax.sig = shortShift64Left( ax.sig, 1 ); 730206917Smarius zx.sig = shortShift64Left( zx.sig, 1 ); 731206917Smarius } 732206917Smarius if ( ax.sig.a0 || ax.sig.a1 ) zx.sig.a1 |= 1; 733206917Smarius return zx; 734206917Smarius 735206917Smarius} 736206917Smarius 737206917Smariusstatic floatX floatXRem( floatX ax, floatX bx ) 738206917Smarius{ 739206917Smarius bits64X negBSig; 740206917Smarius flag lastQuotientBit; 741206917Smarius bits64X savedASig; 742206917Smarius 743206917Smarius if ( ax.isNaN ) return ax; 744206917Smarius if ( bx.isNaN ) return bx; 745206917Smarius if ( ax.isInf || bx.isZero ) return floatXInvalid(); 746206917Smarius if ( ax.isZero || bx.isInf ) return ax; 747206917Smarius --bx.exp; 748206917Smarius if ( ax.exp < bx.exp ) return ax; 749206917Smarius bx.sig = shortShift64Left( bx.sig, 1 ); 750206917Smarius negBSig = neg64( bx.sig ); 751206917Smarius while ( bx.exp < ax.exp ) { 752206917Smarius if ( le64( bx.sig, ax.sig ) ) ax.sig = add64( ax.sig, negBSig ); 753206917Smarius ax.sig = shortShift64Left( ax.sig, 1 ); 754206917Smarius --ax.exp; 755206917Smarius } 756206917Smarius lastQuotientBit = le64( bx.sig, ax.sig ); 757206917Smarius if ( lastQuotientBit ) ax.sig = add64( ax.sig, negBSig ); 758206917Smarius savedASig = ax.sig; 759206917Smarius ax.sig = neg64( add64( ax.sig, negBSig ) ); 760206917Smarius if ( lt64( ax.sig, savedASig ) ) { 761206917Smarius ax.sign = ! ax.sign; 762206917Smarius } 763206917Smarius else if ( lt64( savedASig, ax.sig ) ) { 764206917Smarius ax.sig = savedASig; 765206917Smarius } 766206917Smarius else { 767206917Smarius if ( lastQuotientBit ) { 768206917Smarius ax.sign = ! ax.sign; 769206917Smarius } 770206917Smarius else { 771206917Smarius ax.sig = savedASig; 772206917Smarius } 773206917Smarius } 774206917Smarius if ( ( ax.sig.a0 == 0 ) && ( ax.sig.a1 == 0 ) ) ax.isZero = TRUE; 775206917Smarius return ax; 776206917Smarius 777206917Smarius} 778206917Smarius 779206917Smariusstatic floatX floatXSqrt( floatX ax ) 780206917Smarius{ 781206917Smarius int8 bitNum; 782206917Smarius bits64X bitSig, savedASig; 783206917Smarius floatX zx; 784206917Smarius 785206917Smarius if ( ax.isNaN || ax.isZero ) return ax; 786206917Smarius if ( ax.sign ) return floatXInvalid(); 787206917Smarius if ( ax.isInf ) return ax; 788206917Smarius zx = ax; 789206917Smarius zx.exp >>= 1; 790206917Smarius if ( ( ax.exp & 1 ) == 0 ) ax.sig = shortShift64RightJamming( ax.sig, 1 ); 791206917Smarius zx.sig.a1 = 0; 792206917Smarius zx.sig.a0 = 0; 793206917Smarius bitSig.a1 = 0; 794206917Smarius bitSig.a0 = 0x00800000; 795206917Smarius for ( bitNum = 0; bitNum < 56; ++bitNum ) { 796206917Smarius savedASig = ax.sig; 797206917Smarius ax.sig = add64( ax.sig, neg64( zx.sig ) ); 798206917Smarius ax.sig = shortShift64Left( ax.sig, 1 ); 799206917Smarius ax.sig = add64( ax.sig, neg64( bitSig ) ); 800206917Smarius if ( ax.sig.a0 & 0x80000000 ) { 801206917Smarius ax.sig = shortShift64Left( savedASig, 1 ); 802206917Smarius } 803206917Smarius else { 804206917Smarius zx.sig.a1 |= bitSig.a1; 805206917Smarius zx.sig.a0 |= bitSig.a0; 806206917Smarius } 807206917Smarius bitSig = shortShift64RightJamming( bitSig, 1 ); 808206917Smarius } 809206917Smarius if ( ax.sig.a0 || ax.sig.a1 ) zx.sig.a1 |= 1; 810206917Smarius return zx; 811206917Smarius 812206917Smarius} 813206917Smarius 814206917Smariusstatic flag floatXEq( floatX ax, floatX bx ) 815206917Smarius{ 816206917Smarius 817206917Smarius if ( ax.isNaN || bx.isNaN ) return FALSE; 818206917Smarius if ( ax.isZero && bx.isZero ) return TRUE; 819206917Smarius if ( ax.sign != bx.sign ) return FALSE; 820206917Smarius if ( ax.isInf || bx.isInf ) return ax.isInf && bx.isInf; 821206917Smarius return ( ax.exp == bx.exp ) && eq64( ax.sig, bx.sig ); 822206917Smarius 823206917Smarius} 824206917Smarius 825206917Smariusstatic flag floatXLe( floatX ax, floatX bx ) 826206917Smarius{ 827206917Smarius 828206917Smarius if ( ax.isNaN || bx.isNaN ) return FALSE; 829206917Smarius if ( ax.isZero && bx.isZero ) return TRUE; 830206917Smarius if ( ax.sign != bx.sign ) return ax.sign; 831206917Smarius if ( ax.sign ) { 832206917Smarius if ( ax.isInf || bx.isZero ) return TRUE; 833206917Smarius if ( bx.isInf || ax.isZero ) return FALSE; 834206917Smarius if ( bx.exp < ax.exp ) return TRUE; 835206917Smarius if ( ax.exp < bx.exp ) return FALSE; 836206917Smarius return le64( bx.sig, ax.sig ); 837206917Smarius } 838206917Smarius else { 839206917Smarius if ( bx.isInf || ax.isZero ) return TRUE; 840206917Smarius if ( ax.isInf || bx.isZero ) return FALSE; 841206917Smarius if ( ax.exp < bx.exp ) return TRUE; 842206917Smarius if ( bx.exp < ax.exp ) return FALSE; 843206917Smarius return le64( ax.sig, bx.sig ); 844206917Smarius } 845206917Smarius 846206917Smarius} 847206917Smarius 848206917Smariusstatic flag floatXLt( floatX ax, floatX bx ) 849206917Smarius{ 850206917Smarius 851206917Smarius if ( ax.isNaN || bx.isNaN ) return FALSE; 852206917Smarius if ( ax.isZero && bx.isZero ) return FALSE; 853206917Smarius if ( ax.sign != bx.sign ) return ax.sign; 854206917Smarius if ( ax.isInf && bx.isInf ) return FALSE; 855206917Smarius if ( ax.sign ) { 856206917Smarius if ( ax.isInf || bx.isZero ) return TRUE; 857206917Smarius if ( bx.isInf || ax.isZero ) return FALSE; 858206917Smarius if ( bx.exp < ax.exp ) return TRUE; 859206917Smarius if ( ax.exp < bx.exp ) return FALSE; 860206917Smarius return lt64( bx.sig, ax.sig ); 861206917Smarius } 862206917Smarius else { 863206917Smarius if ( bx.isInf || ax.isZero ) return TRUE; 864206917Smarius if ( ax.isInf || bx.isZero ) return FALSE; 865206917Smarius if ( ax.exp < bx.exp ) return TRUE; 866206917Smarius if ( bx.exp < ax.exp ) return FALSE; 867206917Smarius return lt64( ax.sig, bx.sig ); 868206917Smarius } 869206917Smarius 870206917Smarius} 871206917Smarius 872206917Smariusfloat32 slow_int32_to_float32( int32 a ) 873206917Smarius{ 874206917Smarius 875206917Smarius return floatXToFloat32( int32ToFloatX( a ) ); 876206917Smarius 877206917Smarius} 878206917Smarius 879206917Smariusfloat64 slow_int32_to_float64( int32 a ) 880206917Smarius{ 881206917Smarius 882206917Smarius return floatXToFloat64( int32ToFloatX( a ) ); 883206917Smarius 884206917Smarius} 885206917Smarius 886206917Smariusint32 slow_float32_to_int32( float32 a ) 887206917Smarius{ 888206917Smarius 889206917Smarius return floatXToInt32( float32ToFloatX( a ) ); 890206917Smarius 891206917Smarius} 892206917Smarius 893206917Smariusint32 slow_float32_to_int32_round_to_zero( float32 a ) 894206917Smarius{ 895206917Smarius int8 savedRoundingMode; 896206917Smarius int32 z; 897206917Smarius 898206917Smarius savedRoundingMode = slow_float_rounding_mode; 899206917Smarius slow_float_rounding_mode = float_round_to_zero; 900206917Smarius z = floatXToInt32( float32ToFloatX( a ) ); 901206917Smarius slow_float_rounding_mode = savedRoundingMode; 902206917Smarius return z; 903206917Smarius 904206917Smarius} 905206917Smarius 906206917Smariusfloat64 slow_float32_to_float64( float32 a ) 907206917Smarius{ 908206917Smarius 909206917Smarius return floatXToFloat64( float32ToFloatX( a ) ); 910206917Smarius 911206917Smarius} 912206917Smarius 913206917Smariusfloat32 slow_float32_round_to_int( float32 a ) 914206917Smarius{ 915206917Smarius 916206917Smarius return floatXToFloat32( floatXRoundToInt( float32ToFloatX( a ) ) ); 917206917Smarius 918206917Smarius} 919206917Smarius 920206917Smariusfloat32 slow_float32_add( float32 a, float32 b ) 921206917Smarius{ 922206917Smarius 923206917Smarius return 924206917Smarius floatXToFloat32( 925206917Smarius floatXAdd( float32ToFloatX( a ), float32ToFloatX( b ) ) ); 926206917Smarius 927206917Smarius} 928206917Smarius 929206917Smariusfloat32 slow_float32_sub( float32 a, float32 b ) 930206917Smarius{ 931206917Smarius 932206917Smarius b ^= 0x80000000; 933206917Smarius return 934206917Smarius floatXToFloat32( 935206917Smarius floatXAdd( float32ToFloatX( a ), float32ToFloatX( b ) ) ); 936206917Smarius 937206917Smarius} 938206917Smarius 939206917Smariusfloat32 slow_float32_mul( float32 a, float32 b ) 940206917Smarius{ 941206917Smarius 942206917Smarius return 943206917Smarius floatXToFloat32( 944206917Smarius floatXMul( float32ToFloatX( a ), float32ToFloatX( b ) ) ); 945206917Smarius 946206917Smarius} 947206917Smarius 948206917Smariusfloat32 slow_float32_div( float32 a, float32 b ) 949206917Smarius{ 950206917Smarius 951206917Smarius return 952206917Smarius floatXToFloat32( 953206917Smarius floatXDiv( float32ToFloatX( a ), float32ToFloatX( b ) ) ); 954206917Smarius 955206917Smarius} 956206917Smarius 957206917Smariusfloat32 slow_float32_rem( float32 a, float32 b ) 958206917Smarius{ 959206917Smarius 960206917Smarius return 961206917Smarius floatXToFloat32( 962206917Smarius floatXRem( float32ToFloatX( a ), float32ToFloatX( b ) ) ); 963206917Smarius 964206917Smarius} 965206917Smarius 966206917Smariusfloat32 slow_float32_sqrt( float32 a ) 967206917Smarius{ 968206917Smarius 969206917Smarius return floatXToFloat32( floatXSqrt( float32ToFloatX( a ) ) ); 970206917Smarius 971206917Smarius} 972206917Smarius 973206917Smariusflag slow_float32_eq( float32 a, float32 b ) 974206917Smarius{ 975206917Smarius 976206917Smarius return floatXEq( float32ToFloatX( a ), float32ToFloatX( b ) ); 977206917Smarius 978206917Smarius} 979206917Smarius 980206917Smariusflag slow_float32_le( float32 a, float32 b ) 981206917Smarius{ 982206917Smarius floatX ax, bx; 983206917Smarius 984206917Smarius ax = float32ToFloatX( a ); 985206917Smarius bx = float32ToFloatX( b ); 986206917Smarius if ( ax.isNaN || bx.isNaN ) { 987206917Smarius slow_float_exception_flags |= float_flag_invalid; 988206917Smarius } 989206917Smarius return floatXLe( ax, bx ); 990206917Smarius 991206917Smarius} 992206917Smarius 993206917Smariusflag slow_float32_lt( float32 a, float32 b ) 994206917Smarius{ 995206917Smarius floatX ax, bx; 996206917Smarius 997206917Smarius ax = float32ToFloatX( a ); 998206917Smarius bx = float32ToFloatX( b ); 999206917Smarius if ( ax.isNaN || bx.isNaN ) { 1000206917Smarius slow_float_exception_flags |= float_flag_invalid; 1001206917Smarius } 1002206917Smarius return floatXLt( ax, bx ); 1003206917Smarius 1004206917Smarius} 1005206917Smarius 1006206917Smariusflag slow_float32_eq_signaling( float32 a, float32 b ) 1007206917Smarius{ 1008206917Smarius floatX ax, bx; 1009206917Smarius 1010206917Smarius ax = float32ToFloatX( a ); 1011206917Smarius bx = float32ToFloatX( b ); 1012206917Smarius if ( ax.isNaN || bx.isNaN ) { 1013206917Smarius slow_float_exception_flags |= float_flag_invalid; 1014206917Smarius } 1015206917Smarius return floatXEq( ax, bx ); 1016206917Smarius 1017206917Smarius} 1018206917Smarius 1019206917Smariusflag slow_float32_le_quiet( float32 a, float32 b ) 1020206917Smarius{ 1021206917Smarius 1022206917Smarius return floatXLe( float32ToFloatX( a ), float32ToFloatX( b ) ); 1023206917Smarius 1024206917Smarius} 1025206917Smarius 1026206917Smariusflag slow_float32_lt_quiet( float32 a, float32 b ) 1027206917Smarius{ 1028206917Smarius 1029206917Smarius return floatXLt( float32ToFloatX( a ), float32ToFloatX( b ) ); 1030206917Smarius 1031206917Smarius} 1032206917Smarius 1033206917Smariusint32 slow_float64_to_int32( float64 a ) 1034206917Smarius{ 1035206917Smarius 1036206917Smarius return floatXToInt32( float64ToFloatX( a ) ); 1037206917Smarius 1038206917Smarius} 1039206917Smarius 1040206917Smariusint32 slow_float64_to_int32_round_to_zero( float64 a ) 1041206917Smarius{ 1042206917Smarius int8 savedRoundingMode; 1043206917Smarius int32 z; 1044206917Smarius 1045206917Smarius savedRoundingMode = slow_float_rounding_mode; 1046206917Smarius slow_float_rounding_mode = float_round_to_zero; 1047206917Smarius z = floatXToInt32( float64ToFloatX( a ) ); 1048206917Smarius slow_float_rounding_mode = savedRoundingMode; 1049206917Smarius return z; 1050206917Smarius 1051206917Smarius} 1052206917Smarius 1053206917Smariusfloat32 slow_float64_to_float32( float64 a ) 1054206917Smarius{ 1055206917Smarius 1056206917Smarius return floatXToFloat32( float64ToFloatX( a ) ); 1057206917Smarius 1058206917Smarius} 1059206917Smarius 1060206917Smariusfloat64 slow_float64_round_to_int( float64 a ) 1061206917Smarius{ 1062206917Smarius 1063206917Smarius return floatXToFloat64( floatXRoundToInt( float64ToFloatX( a ) ) ); 1064206917Smarius 1065206917Smarius} 1066206917Smarius 1067206917Smariusfloat64 slow_float64_add( float64 a, float64 b ) 1068206917Smarius{ 1069206917Smarius 1070206917Smarius return 1071206917Smarius floatXToFloat64( 1072206917Smarius floatXAdd( float64ToFloatX( a ), float64ToFloatX( b ) ) ); 1073206917Smarius 1074206917Smarius} 1075206917Smarius 1076206917Smariusfloat64 slow_float64_sub( float64 a, float64 b ) 1077206917Smarius{ 1078206917Smarius 1079206917Smarius#ifdef BITS64 1080206917Smarius b ^= LIT64( 0x8000000000000000 ); 1081206917Smarius#else 1082206917Smarius b.high ^= 0x80000000; 1083206917Smarius#endif 1084206917Smarius return 1085206917Smarius floatXToFloat64( 1086206917Smarius floatXAdd( float64ToFloatX( a ), float64ToFloatX( b ) ) ); 1087206917Smarius 1088206917Smarius} 1089206917Smarius 1090206917Smariusfloat64 slow_float64_mul( float64 a, float64 b ) 1091206917Smarius{ 1092206917Smarius 1093206917Smarius return 1094206917Smarius floatXToFloat64( 1095206917Smarius floatXMul( float64ToFloatX( a ), float64ToFloatX( b ) ) ); 1096206917Smarius 1097206917Smarius} 1098206917Smarius 1099206917Smariusfloat64 slow_float64_div( float64 a, float64 b ) 1100206917Smarius{ 1101206917Smarius 1102206917Smarius return 1103206917Smarius floatXToFloat64( 1104206917Smarius floatXDiv( float64ToFloatX( a ), float64ToFloatX( b ) ) ); 1105206917Smarius 1106206917Smarius} 1107206917Smarius 1108206917Smariusfloat64 slow_float64_rem( float64 a, float64 b ) 1109206917Smarius{ 1110206917Smarius 1111206917Smarius return 1112206917Smarius floatXToFloat64( 1113206917Smarius floatXRem( float64ToFloatX( a ), float64ToFloatX( b ) ) ); 1114206917Smarius 1115206917Smarius} 1116206917Smarius 1117206917Smariusfloat64 slow_float64_sqrt( float64 a ) 1118206917Smarius{ 1119206917Smarius 1120206917Smarius return floatXToFloat64( floatXSqrt( float64ToFloatX( a ) ) ); 1121206917Smarius 1122206917Smarius} 1123206917Smarius 1124206917Smariusflag slow_float64_eq( float64 a, float64 b ) 1125206917Smarius{ 1126206917Smarius 1127206917Smarius return floatXEq( float64ToFloatX( a ), float64ToFloatX( b ) ); 1128206917Smarius 1129206917Smarius} 1130206917Smarius 1131206917Smariusflag slow_float64_le( float64 a, float64 b ) 1132206917Smarius{ 1133206917Smarius floatX ax, bx; 1134206917Smarius 1135206917Smarius ax = float64ToFloatX( a ); 1136206917Smarius bx = float64ToFloatX( b ); 1137206917Smarius if ( ax.isNaN || bx.isNaN ) { 1138206917Smarius slow_float_exception_flags |= float_flag_invalid; 1139206917Smarius } 1140206917Smarius return floatXLe( ax, bx ); 1141206917Smarius 1142206917Smarius} 1143206917Smarius 1144206917Smariusflag slow_float64_lt( float64 a, float64 b ) 1145206917Smarius{ 1146206917Smarius floatX ax, bx; 1147206917Smarius 1148206917Smarius ax = float64ToFloatX( a ); 1149206917Smarius bx = float64ToFloatX( b ); 1150206917Smarius if ( ax.isNaN || bx.isNaN ) { 1151206917Smarius slow_float_exception_flags |= float_flag_invalid; 1152206917Smarius } 1153206917Smarius return floatXLt( ax, bx ); 1154206917Smarius 1155206917Smarius} 1156206917Smarius 1157206917Smariusflag slow_float64_eq_signaling( float64 a, float64 b ) 1158206917Smarius{ 1159206917Smarius floatX ax, bx; 1160206917Smarius 1161206917Smarius ax = float64ToFloatX( a ); 1162206917Smarius bx = float64ToFloatX( b ); 1163206917Smarius if ( ax.isNaN || bx.isNaN ) { 1164206917Smarius slow_float_exception_flags |= float_flag_invalid; 1165206917Smarius } 1166206917Smarius return floatXEq( ax, bx ); 1167206917Smarius 1168206917Smarius} 1169206917Smarius 1170206917Smariusflag slow_float64_le_quiet( float64 a, float64 b ) 1171206917Smarius{ 1172206917Smarius 1173206917Smarius return floatXLe( float64ToFloatX( a ), float64ToFloatX( b ) ); 1174206917Smarius 1175206917Smarius} 1176206917Smarius 1177206917Smariusflag slow_float64_lt_quiet( float64 a, float64 b ) 1178206917Smarius{ 1179206917Smarius 1180206917Smarius return floatXLt( float64ToFloatX( a ), float64ToFloatX( b ) ); 1181206917Smarius 1182206917Smarius} 1183206917Smarius 1184