1 //===-- addsf3.S - Adds two single precision floating pointer numbers-----===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the __addsf3 (single precision floating pointer number
10 // addition with the IEEE-754 default rounding (to nearest, ties to even)
11 // function for the ARM Thumb1 ISA.
13 //===----------------------------------------------------------------------===//
15 #include "../assembly.h"
16 #define significandBits 23
24 DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_fadd, __addsf3)
26 DEFINE_COMPILERRT_THUMB_FUNCTION(__addsf3)
27 push {r4, r5, r6, r7, lr}
28 // Get the absolute value of a and b.
31 lsrs r2, r2, #1 // aAbs
32 beq LOCAL_LABEL(a_zero_nan_inf)
33 lsrs r3, r3, #1 // bAbs
34 beq LOCAL_LABEL(zero_nan_inf)
36 // Detect if a or b is infinity or Nan.
37 lsrs r6, r2, #(significandBits)
38 lsrs r7, r3, #(significandBits)
40 beq LOCAL_LABEL(zero_nan_inf)
42 beq LOCAL_LABEL(zero_nan_inf)
44 // Swap Rep and Abs so that a and aAbs has the larger absolute value.
46 bhs LOCAL_LABEL(no_swap)
55 // Get the significands and shift them to give us round, guard and sticky.
56 lsls r4, r0, #(typeWidth - significandBits)
57 lsrs r4, r4, #(typeWidth - significandBits - 3) // aSignificand << 3
58 lsls r5, r1, #(typeWidth - significandBits)
59 lsrs r5, r5, #(typeWidth - significandBits - 3) // bSignificand << 3
61 // Get the implicitBit.
63 lsls r6, r6, #(significandBits + 3)
65 // Get aExponent and set implicit bit if necessary.
66 lsrs r2, r2, #(significandBits)
67 beq LOCAL_LABEL(a_done_implicit_bit)
69 LOCAL_LABEL(a_done_implicit_bit):
71 // Get bExponent and set implicit bit if necessary.
72 lsrs r3, r3, #(significandBits)
73 beq LOCAL_LABEL(b_done_implicit_bit)
75 LOCAL_LABEL(b_done_implicit_bit):
77 // Get the difference in exponents.
79 beq LOCAL_LABEL(done_align)
81 // If b is denormal, then a must be normal as align > 0, and we only need to
82 // right shift bSignificand by (align - 1) bits.
88 // No longer needs bExponent. r3 is dead here.
89 // Set sticky bits of b: sticky = bSignificand << (typeWidth - align).
98 // bSignificand = bSignificand >> align | sticky;
101 bne LOCAL_LABEL(done_align)
102 movs r5, #1 // sticky; b is known to be non-zero.
104 LOCAL_LABEL(done_align):
105 // isSubtraction = (aRep ^ bRep) >> 31;
109 bne LOCAL_LABEL(do_substraction)
111 // Same sign, do Addition.
113 // aSignificand += bSignificand;
118 lsls r6, r6, #(significandBits + 3 + 1)
121 beq LOCAL_LABEL(form_result)
122 // If the addition carried up, we need to right-shift the result and
123 // adjust the exponent.
126 ands r7, r6 // sticky = aSignificand & 1;
128 orrs r4, r7 // result Significand
129 adds r2, #1 // result Exponent
130 // If we have overflowed the type, return +/- infinity.
132 beq LOCAL_LABEL(ret_inf)
134 LOCAL_LABEL(form_result):
135 // Shift the sign, exponent and significand into place.
136 lsrs r0, #(typeWidth - 1)
137 lsls r0, #(typeWidth - 1) // Get Sign.
138 lsls r2, #(significandBits)
141 lsls r4, #(typeWidth - significandBits - 3)
142 lsrs r4, #(typeWidth - significandBits)
145 // Final rounding. The result may overflow to infinity, but that is the
146 // correct result in that case.
147 // roundGuardSticky = aSignificand & 0x7;
150 // if (roundGuardSticky > 0x4) result++;
153 blt LOCAL_LABEL(done_round)
156 pop {r4, r5, r6, r7, pc}
159 // if (roundGuardSticky == 0x4) result += result & 1;
162 bcc LOCAL_LABEL(done_round)
164 LOCAL_LABEL(done_round):
165 pop {r4, r5, r6, r7, pc}
167 LOCAL_LABEL(do_substraction):
168 subs r4, r4, r5 // aSignificand -= bSignificand;
169 beq LOCAL_LABEL(ret_zero)
172 beq LOCAL_LABEL(form_result) // if a's exp is 0, no need to normalize.
173 // If partial cancellation occured, we need to left-shift the result
174 // and adjust the exponent:
175 lsrs r6, r6, #(significandBits + 3)
176 bne LOCAL_LABEL(form_result)
178 push {r0, r1, r2, r3}
180 bl SYMBOL_NAME(__clzsi2)
183 // shift = rep_clz(aSignificand) - rep_clz(implicitBit << 3);
184 subs r5, r5, #(typeWidth - significandBits - 3 - 1)
185 // aSignificand <<= shift; aExponent -= shift;
188 bgt LOCAL_LABEL(form_result)
190 // Do normalization if aExponent <= 0.
192 subs r6, r6, r2 // 1 - aExponent;
193 movs r2, #0 // aExponent = 0;
194 movs r3, #(typeWidth) // bExponent is dead.
197 lsls r7, r3 // stickyBit = (bool)(aSignificant << (typeWidth - align))
201 lsrs r4, r6 // aSignificand >> shift
203 b LOCAL_LABEL(form_result)
205 LOCAL_LABEL(ret_zero):
207 pop {r4, r5, r6, r7, pc}
210 LOCAL_LABEL(a_zero_nan_inf):
213 LOCAL_LABEL(zero_nan_inf):
214 // Here r2 has aAbs, r3 has bAbs
216 lsls r4, r4, #(significandBits) // Make +inf.
219 bhi LOCAL_LABEL(a_is_nan)
221 bhi LOCAL_LABEL(b_is_nan)
224 bne LOCAL_LABEL(a_is_rational)
226 eors r1, r0 // aRep ^ bRep.
228 lsls r6, r6, #(typeWidth - 1) // get sign mask.
229 cmp r1, r6 // if they only differ on sign bit, it's -INF + INF
230 beq LOCAL_LABEL(a_is_nan)
231 pop {r4, r5, r6, r7, pc}
233 LOCAL_LABEL(a_is_rational):
235 bne LOCAL_LABEL(b_is_rational)
237 pop {r4, r5, r6, r7, pc}
239 LOCAL_LABEL(b_is_rational):
240 // either a or b or both are zero.
242 beq LOCAL_LABEL(both_zero)
243 cmp r2, #0 // is absA 0 ?
244 beq LOCAL_LABEL(ret_b)
245 pop {r4, r5, r6, r7, pc}
247 LOCAL_LABEL(both_zero):
248 ands r0, r1 // +0 + -0 = +0
249 pop {r4, r5, r6, r7, pc}
255 pop {r4, r5, r6, r7, pc}
257 LOCAL_LABEL(b_is_nan):
259 LOCAL_LABEL(a_is_nan):
261 lsls r1, r1, #(significandBits -1) // r1 is quiet bit.
263 pop {r4, r5, r6, r7, pc}
265 LOCAL_LABEL(ret_inf):
267 lsls r4, r4, #(significandBits)
269 lsrs r0, r0, #(significandBits)
270 lsls r0, r0, #(significandBits)
271 pop {r4, r5, r6, r7, pc}
274 END_COMPILERRT_FUNCTION(__addsf3)
276 NO_EXEC_STACK_DIRECTIVE