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