1 //===-- lib/addsf3.c - Single-precision addition ------------------*- C -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements single-precision soft-float addition with the IEEE-754
11 // default rounding (to nearest, ties to even).
13 //===----------------------------------------------------------------------===//
15 #define SINGLE_PRECISION
18 ARM_EABI_FNALIAS(fadd
, addsf3
);
20 fp_t
__addsf3(fp_t a
, fp_t b
) {
22 rep_t aRep
= toRep(a
);
23 rep_t bRep
= toRep(b
);
24 const rep_t aAbs
= aRep
& absMask
;
25 const rep_t bAbs
= bRep
& absMask
;
27 // Detect if a or b is zero, infinity, or NaN.
28 if (aAbs
- 1U >= infRep
- 1U || bAbs
- 1U >= infRep
- 1U) {
30 // NaN + anything = qNaN
31 if (aAbs
> infRep
) return fromRep(toRep(a
) | quietBit
);
32 // anything + NaN = qNaN
33 if (bAbs
> infRep
) return fromRep(toRep(b
) | quietBit
);
36 // +/-infinity + -/+infinity = qNaN
37 if ((toRep(a
) ^ toRep(b
)) == signBit
) return fromRep(qnanRep
);
38 // +/-infinity + anything remaining = +/- infinity
42 // anything remaining + +/-infinity = +/-infinity
43 if (bAbs
== infRep
) return b
;
45 // zero + anything = anything
47 // but we need to get the sign right for zero + zero
48 if (!bAbs
) return fromRep(toRep(a
) & toRep(b
));
52 // anything + zero = anything
56 // Swap a and b if necessary so that a has the larger absolute value.
58 const rep_t temp
= aRep
;
63 // Extract the exponent and significand from the (possibly swapped) a and b.
64 int aExponent
= aRep
>> significandBits
& maxExponent
;
65 int bExponent
= bRep
>> significandBits
& maxExponent
;
66 rep_t aSignificand
= aRep
& significandMask
;
67 rep_t bSignificand
= bRep
& significandMask
;
69 // Normalize any denormals, and adjust the exponent accordingly.
70 if (aExponent
== 0) aExponent
= normalize(&aSignificand
);
71 if (bExponent
== 0) bExponent
= normalize(&bSignificand
);
73 // The sign of the result is the sign of the larger operand, a. If they
74 // have opposite signs, we are performing a subtraction; otherwise addition.
75 const rep_t resultSign
= aRep
& signBit
;
76 const bool subtraction
= (aRep
^ bRep
) & signBit
;
78 // Shift the significands to give us round, guard and sticky, and or in the
79 // implicit significand bit. (If we fell through from the denormal path it
80 // was already set by normalize( ), but setting it twice won't hurt
82 aSignificand
= (aSignificand
| implicitBit
) << 3;
83 bSignificand
= (bSignificand
| implicitBit
) << 3;
85 // Shift the significand of b by the difference in exponents, with a sticky
86 // bottom bit to get rounding correct.
87 const int align
= aExponent
- bExponent
;
89 if (align
< typeWidth
) {
90 const bool sticky
= bSignificand
<< (typeWidth
- align
);
91 bSignificand
= bSignificand
>> align
| sticky
;
93 bSignificand
= 1; // sticky; b is known to be non-zero.
98 aSignificand
-= bSignificand
;
100 // If a == -b, return +zero.
101 if (aSignificand
== 0) return fromRep(0);
103 // If partial cancellation occured, we need to left-shift the result
104 // and adjust the exponent:
105 if (aSignificand
< implicitBit
<< 3) {
106 const int shift
= rep_clz(aSignificand
) - rep_clz(implicitBit
<< 3);
107 aSignificand
<<= shift
;
112 else /* addition */ {
113 aSignificand
+= bSignificand
;
115 // If the addition carried up, we need to right-shift the result and
116 // adjust the exponent:
117 if (aSignificand
& implicitBit
<< 4) {
118 const bool sticky
= aSignificand
& 1;
119 aSignificand
= aSignificand
>> 1 | sticky
;
124 // If we have overflowed the type, return +/- infinity:
125 if (aExponent
>= maxExponent
) return fromRep(infRep
| resultSign
);
127 if (aExponent
<= 0) {
128 // Result is denormal before rounding; the exponent is zero and we
129 // need to shift the significand.
130 const int shift
= 1 - aExponent
;
131 const bool sticky
= aSignificand
<< (typeWidth
- shift
);
132 aSignificand
= aSignificand
>> shift
| sticky
;
136 // Low three bits are round, guard, and sticky.
137 const int roundGuardSticky
= aSignificand
& 0x7;
139 // Shift the significand into place, and mask off the implicit bit.
140 rep_t result
= aSignificand
>> 3 & significandMask
;
142 // Insert the exponent and sign.
143 result
|= (rep_t
)aExponent
<< significandBits
;
144 result
|= resultSign
;
146 // Final rounding. The result may overflow to infinity, but that is the
147 // correct result in that case.
148 if (roundGuardSticky
> 0x4) result
++;
149 if (roundGuardSticky
== 0x4) result
+= result
& 1;
150 return fromRep(result
);