1//===----- lib/fp_add_impl.inc - floaing point addition -----------*- C -*-===// 2// 3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4// See https://llvm.org/LICENSE.txt for license information. 5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6// 7//===----------------------------------------------------------------------===// 8// 9// This file implements soft-float addition with the IEEE-754 default rounding 10// (to nearest, ties to even). 11// 12//===----------------------------------------------------------------------===// 13 14#include "fp_lib.h" 15#include "fp_mode.h" 16 17static __inline fp_t __addXf3__(fp_t a, fp_t b) { 18 rep_t aRep = toRep(a); 19 rep_t bRep = toRep(b); 20 const rep_t aAbs = aRep & absMask; 21 const rep_t bAbs = bRep & absMask; 22 23 // Detect if a or b is zero, infinity, or NaN. 24 if (aAbs - REP_C(1) >= infRep - REP_C(1) || 25 bAbs - REP_C(1) >= infRep - REP_C(1)) { 26 // NaN + anything = qNaN 27 if (aAbs > infRep) 28 return fromRep(toRep(a) | quietBit); 29 // anything + NaN = qNaN 30 if (bAbs > infRep) 31 return fromRep(toRep(b) | quietBit); 32 33 if (aAbs == infRep) { 34 // +/-infinity + -/+infinity = qNaN 35 if ((toRep(a) ^ toRep(b)) == signBit) 36 return fromRep(qnanRep); 37 // +/-infinity + anything remaining = +/- infinity 38 else 39 return a; 40 } 41 42 // anything remaining + +/-infinity = +/-infinity 43 if (bAbs == infRep) 44 return b; 45 46 // zero + anything = anything 47 if (!aAbs) { 48 // We need to get the sign right for zero + zero. 49 if (!bAbs) 50 return fromRep(toRep(a) & toRep(b)); 51 else 52 return b; 53 } 54 55 // anything + zero = anything 56 if (!bAbs) 57 return a; 58 } 59 60 // Swap a and b if necessary so that a has the larger absolute value. 61 if (bAbs > aAbs) { 62 const rep_t temp = aRep; 63 aRep = bRep; 64 bRep = temp; 65 } 66 67 // Extract the exponent and significand from the (possibly swapped) a and b. 68 int aExponent = aRep >> significandBits & maxExponent; 69 int bExponent = bRep >> significandBits & maxExponent; 70 rep_t aSignificand = aRep & significandMask; 71 rep_t bSignificand = bRep & significandMask; 72 73 // Normalize any denormals, and adjust the exponent accordingly. 74 if (aExponent == 0) 75 aExponent = normalize(&aSignificand); 76 if (bExponent == 0) 77 bExponent = normalize(&bSignificand); 78 79 // The sign of the result is the sign of the larger operand, a. If they 80 // have opposite signs, we are performing a subtraction. Otherwise, we 81 // perform addition. 82 const rep_t resultSign = aRep & signBit; 83 const bool subtraction = (aRep ^ bRep) & signBit; 84 85 // Shift the significands to give us round, guard and sticky, and set the 86 // implicit significand bit. If we fell through from the denormal path it 87 // was already set by normalize( ), but setting it twice won't hurt 88 // anything. 89 aSignificand = (aSignificand | implicitBit) << 3; 90 bSignificand = (bSignificand | implicitBit) << 3; 91 92 // Shift the significand of b by the difference in exponents, with a sticky 93 // bottom bit to get rounding correct. 94 const unsigned int align = aExponent - bExponent; 95 if (align) { 96 if (align < typeWidth) { 97 const bool sticky = (bSignificand << (typeWidth - align)) != 0; 98 bSignificand = bSignificand >> align | sticky; 99 } else { 100 bSignificand = 1; // Set the sticky bit. b is known to be non-zero. 101 } 102 } 103 if (subtraction) { 104 aSignificand -= bSignificand; 105 // If a == -b, return +zero. 106 if (aSignificand == 0) 107 return fromRep(0); 108 109 // If partial cancellation occured, we need to left-shift the result 110 // and adjust the exponent. 111 if (aSignificand < implicitBit << 3) { 112 const int shift = rep_clz(aSignificand) - rep_clz(implicitBit << 3); 113 aSignificand <<= shift; 114 aExponent -= shift; 115 } 116 } else /* addition */ { 117 aSignificand += bSignificand; 118 119 // If the addition carried up, we need to right-shift the result and 120 // adjust the exponent. 121 if (aSignificand & implicitBit << 4) { 122 const bool sticky = aSignificand & 1; 123 aSignificand = aSignificand >> 1 | sticky; 124 aExponent += 1; 125 } 126 } 127 128 // If we have overflowed the type, return +/- infinity. 129 if (aExponent >= maxExponent) 130 return fromRep(infRep | resultSign); 131 132 if (aExponent <= 0) { 133 // The result is denormal before rounding. The exponent is zero and we 134 // need to shift the significand. 135 const int shift = 1 - aExponent; 136 const bool sticky = (aSignificand << (typeWidth - shift)) != 0; 137 aSignificand = aSignificand >> shift | sticky; 138 aExponent = 0; 139 } 140 141 // Low three bits are round, guard, and sticky. 142 const int roundGuardSticky = aSignificand & 0x7; 143 144 // Shift the significand into place, and mask off the implicit bit. 145 rep_t result = aSignificand >> 3 & significandMask; 146 147 // Insert the exponent and sign. 148 result |= (rep_t)aExponent << significandBits; 149 result |= resultSign; 150 151 // Perform the final rounding. The result may overflow to infinity, but 152 // that is the correct result in that case. 153 switch (__fe_getround()) { 154 case CRT_FE_TONEAREST: 155 if (roundGuardSticky > 0x4) 156 result++; 157 if (roundGuardSticky == 0x4) 158 result += result & 1; 159 break; 160 case CRT_FE_DOWNWARD: 161 if (resultSign && roundGuardSticky) result++; 162 break; 163 case CRT_FE_UPWARD: 164 if (!resultSign && roundGuardSticky) result++; 165 break; 166 case CRT_FE_TOWARDZERO: 167 break; 168 } 169 if (roundGuardSticky) 170 __fe_raise_inexact(); 171 return fromRep(result); 172} 173