blob: c0e8d8e70dc8cd4f1ec39d9a29ad770d83628031 [file] [log] [blame]
Stephen Canon5c6d2ec2010-07-01 17:58:24 +00001//===-- lib/addsf3.c - Single-precision addition and subtraction --*- C -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
Howard Hinnant9ad441f2010-11-16 22:13:33 +00005// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
Stephen Canon5c6d2ec2010-07-01 17:58:24 +00007//
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//===----------------------------------------------------------------------===//
Stephen Canone5086322010-07-01 15:52:42 +000014
15#define SINGLE_PRECISION
16#include "fp_lib.h"
17
Stephen Canone5086322010-07-01 15:52:42 +000018fp_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