]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | //===-- lib/addsf3.c - Single-precision addition ------------------*- C -*-===// |
2 | // | |
3 | // The LLVM Compiler Infrastructure | |
4 | // | |
5 | // This file is dual licensed under the MIT and the University of Illinois Open | |
6 | // Source Licenses. See LICENSE.TXT for details. | |
7 | // | |
8 | //===----------------------------------------------------------------------===// | |
9 | // | |
10 | // This file implements single-precision soft-float addition with the IEEE-754 | |
11 | // default rounding (to nearest, ties to even). | |
12 | // | |
13 | //===----------------------------------------------------------------------===// | |
14 | ||
15 | #define SINGLE_PRECISION | |
16 | #include "fp_lib.h" | |
17 | ||
18 | ARM_EABI_FNALIAS(fadd, addsf3) | |
19 | ||
20 | fp_t __addsf3(fp_t a, fp_t b) { | |
21 | ||
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; | |
26 | ||
27 | // Detect if a or b is zero, infinity, or NaN. | |
28 | if (aAbs - 1U >= infRep - 1U || bAbs - 1U >= infRep - 1U) { | |
29 | ||
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); | |
34 | ||
35 | if (aAbs == infRep) { | |
36 | // +/-infinity + -/+infinity = qNaN | |
37 | if ((toRep(a) ^ toRep(b)) == signBit) return fromRep(qnanRep); | |
38 | // +/-infinity + anything remaining = +/- infinity | |
39 | else return a; | |
40 | } | |
41 | ||
42 | // anything remaining + +/-infinity = +/-infinity | |
43 | if (bAbs == infRep) return b; | |
44 | ||
45 | // zero + anything = anything | |
46 | if (!aAbs) { | |
47 | // but we need to get the sign right for zero + zero | |
48 | if (!bAbs) return fromRep(toRep(a) & toRep(b)); | |
49 | else return b; | |
50 | } | |
51 | ||
52 | // anything + zero = anything | |
53 | if (!bAbs) return a; | |
54 | } | |
55 | ||
56 | // Swap a and b if necessary so that a has the larger absolute value. | |
57 | if (bAbs > aAbs) { | |
58 | const rep_t temp = aRep; | |
59 | aRep = bRep; | |
60 | bRep = temp; | |
61 | } | |
62 | ||
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; | |
68 | ||
69 | // Normalize any denormals, and adjust the exponent accordingly. | |
70 | if (aExponent == 0) aExponent = normalize(&aSignificand); | |
71 | if (bExponent == 0) bExponent = normalize(&bSignificand); | |
72 | ||
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; | |
77 | ||
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 | |
81 | // anything.) | |
82 | aSignificand = (aSignificand | implicitBit) << 3; | |
83 | bSignificand = (bSignificand | implicitBit) << 3; | |
84 | ||
85 | // Shift the significand of b by the difference in exponents, with a sticky | |
86 | // bottom bit to get rounding correct. | |
87 | const unsigned int align = aExponent - bExponent; | |
88 | if (align) { | |
89 | if (align < typeWidth) { | |
90 | const bool sticky = bSignificand << (typeWidth - align); | |
91 | bSignificand = bSignificand >> align | sticky; | |
92 | } else { | |
93 | bSignificand = 1; // sticky; b is known to be non-zero. | |
94 | } | |
95 | } | |
96 | ||
97 | if (subtraction) { | |
98 | aSignificand -= bSignificand; | |
99 | ||
100 | // If a == -b, return +zero. | |
101 | if (aSignificand == 0) return fromRep(0); | |
102 | ||
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; | |
108 | aExponent -= shift; | |
109 | } | |
110 | } | |
111 | ||
112 | else /* addition */ { | |
113 | aSignificand += bSignificand; | |
114 | ||
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; | |
120 | aExponent += 1; | |
121 | } | |
122 | } | |
123 | ||
124 | // If we have overflowed the type, return +/- infinity: | |
125 | if (aExponent >= maxExponent) return fromRep(infRep | resultSign); | |
126 | ||
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; | |
133 | aExponent = 0; | |
134 | } | |
135 | ||
136 | // Low three bits are round, guard, and sticky. | |
137 | const int roundGuardSticky = aSignificand & 0x7; | |
138 | ||
139 | // Shift the significand into place, and mask off the implicit bit. | |
140 | rep_t result = aSignificand >> 3 & significandMask; | |
141 | ||
142 | // Insert the exponent and sign. | |
143 | result |= (rep_t)aExponent << significandBits; | |
144 | result |= resultSign; | |
145 | ||
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); | |
151 | } |