1 // SPDX-License-Identifier: BSD-3-Clause 2 3 /*============================================================================ 4 5 This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic 6 Package, Release 3a, by John R. Hauser. 7 8 Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. 9 All rights reserved. 10 11 Redistribution and use in source and binary forms, with or without 12 modification, are permitted provided that the following conditions are met: 13 14 1. Redistributions of source code must retain the above copyright notice, 15 this list of conditions, and the following disclaimer. 16 17 2. Redistributions in binary form must reproduce the above copyright notice, 18 this list of conditions, and the following disclaimer in the documentation 19 and/or other materials provided with the distribution. 20 21 3. Neither the name of the University nor the names of its contributors may 22 be used to endorse or promote products derived from this software without 23 specific prior written permission. 24 25 THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY 26 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 27 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE 28 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 29 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 30 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 31 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 32 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 33 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 34 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35 36 =============================================================================*/ 37 38 #include <stdbool.h> 39 #include <stdint.h> 40 #include "platform.h" 41 #include "internals.h" 42 #include "specialize.h" 43 #include "softfloat.h" 44 45 extFloat80_t softfloat_subMagsExtF80(uint_fast16_t uiA64,uint_fast64_t uiA0,uint_fast16_t uiB64,uint_fast64_t uiB0,bool signZ)46 softfloat_subMagsExtF80( 47 uint_fast16_t uiA64, 48 uint_fast64_t uiA0, 49 uint_fast16_t uiB64, 50 uint_fast64_t uiB0, 51 bool signZ 52 ) 53 { 54 int_fast32_t expA; 55 uint_fast64_t sigA; 56 int_fast32_t expB; 57 uint_fast64_t sigB; 58 int_fast32_t expDiff; 59 uint_fast16_t uiZ64; 60 uint_fast64_t uiZ0; 61 int_fast32_t expZ; 62 uint_fast64_t sigExtra; 63 struct uint128 sig128, uiZ; 64 union { struct extFloat80M s; extFloat80_t f; } uZ; 65 66 /*------------------------------------------------------------------------ 67 *------------------------------------------------------------------------*/ 68 expA = expExtF80UI64( uiA64 ); 69 sigA = uiA0; 70 expB = expExtF80UI64( uiB64 ); 71 sigB = uiB0; 72 /*------------------------------------------------------------------------ 73 *------------------------------------------------------------------------*/ 74 expDiff = expA - expB; 75 if ( 0 < expDiff ) goto expABigger; 76 if ( expDiff < 0 ) goto expBBigger; 77 if ( expA == 0x7FFF ) { 78 if ( (sigA | sigB) & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) { 79 goto propagateNaN; 80 } 81 softfloat_raiseFlags( softfloat_flag_invalid ); 82 uiZ64 = defaultNaNExtF80UI64; 83 uiZ0 = defaultNaNExtF80UI0; 84 goto uiZ; 85 } 86 /*------------------------------------------------------------------------ 87 *------------------------------------------------------------------------*/ 88 expZ = expA; 89 if ( ! expZ ) expZ = 1; 90 sigExtra = 0; 91 if ( sigB < sigA ) goto aBigger; 92 if ( sigA < sigB ) goto bBigger; 93 uiZ64 = 94 packToExtF80UI64( (softfloat_roundingMode == softfloat_round_min), 0 ); 95 uiZ0 = 0; 96 goto uiZ; 97 /*------------------------------------------------------------------------ 98 *------------------------------------------------------------------------*/ 99 expBBigger: 100 if ( expB == 0x7FFF ) { 101 if ( sigB & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; 102 uiZ64 = packToExtF80UI64( signZ ^ 1, 0x7FFF ); 103 uiZ0 = UINT64_C( 0x8000000000000000 ); 104 goto uiZ; 105 } 106 if ( ! expA ) { 107 ++expDiff; 108 sigExtra = 0; 109 if ( ! expDiff ) goto newlyAlignedBBigger; 110 } 111 sig128 = softfloat_shiftRightJam128( sigA, 0, -expDiff ); 112 sigA = sig128.v64; 113 sigExtra = sig128.v0; 114 newlyAlignedBBigger: 115 expZ = expB; 116 bBigger: 117 signZ ^= 1; 118 sig128 = softfloat_sub128( sigB, 0, sigA, sigExtra ); 119 goto normRoundPack; 120 /*------------------------------------------------------------------------ 121 *------------------------------------------------------------------------*/ 122 expABigger: 123 if ( expA == 0x7FFF ) { 124 if ( sigA & UINT64_C( 0x7FFFFFFFFFFFFFFF ) ) goto propagateNaN; 125 uiZ64 = uiA64; 126 uiZ0 = uiA0; 127 goto uiZ; 128 } 129 if ( ! expB ) { 130 --expDiff; 131 sigExtra = 0; 132 if ( ! expDiff ) goto newlyAlignedABigger; 133 } 134 sig128 = softfloat_shiftRightJam128( sigB, 0, expDiff ); 135 sigB = sig128.v64; 136 sigExtra = sig128.v0; 137 newlyAlignedABigger: 138 expZ = expA; 139 aBigger: 140 sig128 = softfloat_sub128( sigA, 0, sigB, sigExtra ); 141 /*------------------------------------------------------------------------ 142 *------------------------------------------------------------------------*/ 143 normRoundPack: 144 return 145 softfloat_normRoundPackToExtF80( 146 signZ, expZ, sig128.v64, sig128.v0, extF80_roundingPrecision ); 147 /*------------------------------------------------------------------------ 148 *------------------------------------------------------------------------*/ 149 propagateNaN: 150 uiZ = softfloat_propagateNaNExtF80UI( uiA64, uiA0, uiB64, uiB0 ); 151 uiZ64 = uiZ.v64; 152 uiZ0 = uiZ.v0; 153 uiZ: 154 uZ.s.signExp = uiZ64; 155 uZ.s.signif = uiZ0; 156 return uZ.f; 157 158 } 159 160