addsf3.S revision 317285
1/*===-- addsf3.S - Adds two single precision floating pointer numbers-----===//
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 the __addsf3 (single precision floating pointer number
11 * addition with the IEEE-754 default rounding (to nearest, ties to even)
12 * function for the ARM Thumb1 ISA.
13 *
14 *===----------------------------------------------------------------------===*/
15
16#include "../assembly.h"
17#define significandBits 23
18#define typeWidth 32
19
20	.syntax unified
21	.text
22  .thumb
23  .p2align 2
24
25DEFINE_AEABI_FUNCTION_ALIAS(__aeabi_fadd, __addsf3)
26
27DEFINE_COMPILERRT_THUMB_FUNCTION(__addsf3)
28  push {r4, r5, r6, r7, lr}
29  // Get the absolute value of a and b.
30  lsls r2, r0, #1
31  lsls r3, r1, #1
32  lsrs r2, r2, #1  /* aAbs */
33  beq  LOCAL_LABEL(a_zero_nan_inf)
34  lsrs r3, r3, #1  /* bAbs */
35  beq  LOCAL_LABEL(zero_nan_inf)
36
37  // Detect if a or b is infinity or Nan.
38  lsrs r6, r2, #(significandBits)
39  lsrs r7, r3, #(significandBits)
40  cmp  r6, #0xFF
41  beq  LOCAL_LABEL(zero_nan_inf)
42  cmp  r7, #0xFF
43  beq  LOCAL_LABEL(zero_nan_inf)
44
45  // Swap Rep and Abs so that a and aAbs has the larger absolute value.
46  cmp r2, r3
47  bhs LOCAL_LABEL(no_swap)
48  movs r4, r0
49  movs r5, r2
50  movs r0, r1
51  movs r2, r3
52  movs r1, r4
53  movs r3, r5
54LOCAL_LABEL(no_swap):
55
56  // Get the significands and shift them to give us round, guard and sticky.
57  lsls r4, r0, #(typeWidth - significandBits)
58  lsrs r4, r4, #(typeWidth - significandBits - 3) /* aSignificand << 3 */
59  lsls r5, r1, #(typeWidth - significandBits)
60  lsrs r5, r5, #(typeWidth - significandBits - 3) /* bSignificand << 3 */
61
62  // Get the implicitBit.
63  movs r6, #1
64  lsls r6, r6, #(significandBits + 3)
65
66  // Get aExponent and set implicit bit if necessary.
67  lsrs r2, r2, #(significandBits)
68  beq LOCAL_LABEL(a_done_implicit_bit)
69  orrs r4, r6
70LOCAL_LABEL(a_done_implicit_bit):
71
72  // Get bExponent and set implicit bit if necessary.
73  lsrs r3, r3, #(significandBits)
74  beq LOCAL_LABEL(b_done_implicit_bit)
75  orrs r5, r6
76LOCAL_LABEL(b_done_implicit_bit):
77
78  // Get the difference in exponents.
79  subs r6, r2, r3
80  beq LOCAL_LABEL(done_align)
81
82  // If b is denormal, then a must be normal as align > 0, and we only need to
83  // right shift bSignificand by (align - 1) bits.
84  cmp  r3, #0
85  bne  1f
86  subs r6, r6, #1
871:
88
89  // No longer needs bExponent. r3 is dead here.
90  // Set sticky bits of b: sticky = bSignificand << (typeWidth - align).
91  movs r3, #(typeWidth)
92  subs r3, r3, r6
93  movs r7, r5
94  lsls r7, r3
95  beq 1f
96  movs r7, #1
971:
98
99  // bSignificand = bSignificand >> align | sticky;
100  lsrs r5, r6
101  orrs r5, r7
102  bne LOCAL_LABEL(done_align)
103  movs r5, #1 //  sticky; b is known to be non-zero.
104
105LOCAL_LABEL(done_align):
106  // isSubtraction = (aRep ^ bRep) >> 31;
107  movs r7, r0
108  eors r7, r1
109  lsrs r7, #31
110  bne LOCAL_LABEL(do_substraction)
111
112  // Same sign, do Addition.
113
114  // aSignificand += bSignificand;
115  adds r4, r4, r5
116
117  // Check carry bit.
118  movs r6, #1
119  lsls r6, r6, #(significandBits + 3 + 1)
120  movs r7, r4
121  ands r7, r6
122  beq LOCAL_LABEL(form_result)
123  // If the addition carried up, we need to right-shift the result and
124  // adjust the exponent.
125  movs r7, r4
126  movs r6, #1
127  ands r7, r6 // sticky = aSignificand & 1;
128  lsrs r4, #1
129  orrs r4, r7  // result Significand
130  adds r2, #1  // result Exponent
131  // If we have overflowed the type, return +/- infinity.
132  cmp  r2, 0xFF
133  beq  LOCAL_LABEL(ret_inf)
134
135LOCAL_LABEL(form_result):
136  // Shift the sign, exponent and significand into place.
137  lsrs r0, #(typeWidth - 1)
138  lsls r0, #(typeWidth - 1) // Get Sign.
139  lsls r2, #(significandBits)
140  orrs r0, r2
141  movs r1, r4
142  lsls r4, #(typeWidth - significandBits - 3)
143  lsrs r4, #(typeWidth - significandBits)
144  orrs r0, r4
145
146  // Final rounding.  The result may overflow to infinity, but that is the
147  // correct result in that case.
148  // roundGuardSticky = aSignificand & 0x7;
149  movs r2, #0x7
150  ands r1, r2
151  // if (roundGuardSticky > 0x4) result++;
152
153  cmp r1, #0x4
154  blt LOCAL_LABEL(done_round)
155  beq 1f
156  adds r0, #1
157  pop {r4, r5, r6, r7, pc}
1581:
159
160  // if (roundGuardSticky == 0x4) result += result & 1;
161  movs r1, r0
162  lsrs r1, #1
163  bcc  LOCAL_LABEL(done_round)
164  adds r0, r0, #1
165LOCAL_LABEL(done_round):
166  pop {r4, r5, r6, r7, pc}
167
168LOCAL_LABEL(do_substraction):
169  subs r4, r4, r5 // aSignificand -= bSignificand;
170  beq  LOCAL_LABEL(ret_zero)
171  movs r6, r4
172  cmp  r2, 0
173  beq  LOCAL_LABEL(form_result) // if a's exp is 0, no need to normalize.
174  // If partial cancellation occured, we need to left-shift the result
175  // and adjust the exponent:
176  lsrs r6, r6, #(significandBits + 3)
177  bne LOCAL_LABEL(form_result)
178
179  push {r0, r1, r2, r3}
180  movs r0, r4
181  bl   __clzsi2
182  movs r5, r0
183  pop {r0, r1, r2, r3}
184  // shift = rep_clz(aSignificand) - rep_clz(implicitBit << 3);
185  subs r5, r5, #(typeWidth - significandBits - 3 - 1)
186  // aSignificand <<= shift; aExponent -= shift;
187  lsls r4, r5
188  subs  r2, r2, r5
189  bgt LOCAL_LABEL(form_result)
190
191  // Do normalization if aExponent <= 0.
192  movs r6, #1
193  subs r6, r6, r2 // 1 - aExponent;
194  movs r2, #0 // aExponent = 0;
195  movs r3, #(typeWidth) // bExponent is dead.
196  subs r3, r3, r6
197  movs r7, r4
198  lsls r7, r3  // stickyBit = (bool)(aSignificant << (typeWidth - align))
199  beq 1f
200  movs r7, #1
2011:
202  lsrs r4, r6 /* aSignificand >> shift */
203  orrs r4, r7
204  b LOCAL_LABEL(form_result)
205
206LOCAL_LABEL(ret_zero):
207  movs r0, #0
208  pop {r4, r5, r6, r7, pc}
209
210
211LOCAL_LABEL(a_zero_nan_inf):
212  lsrs r3, r3, #1
213
214LOCAL_LABEL(zero_nan_inf):
215  // Here  r2 has aAbs, r3 has bAbs
216  movs r4, #0xFF
217  lsls r4, r4, #(significandBits) // Make +inf.
218
219  cmp r2, r4
220  bhi LOCAL_LABEL(a_is_nan)
221  cmp r3, r4
222  bhi LOCAL_LABEL(b_is_nan)
223
224  cmp r2, r4
225  bne LOCAL_LABEL(a_is_rational)
226  // aAbs is INF.
227  eors r1, r0 // aRep ^ bRep.
228  movs r6, #1
229  lsls r6, r6, #(typeWidth - 1) // get sign mask.
230  cmp r1, r6 // if they only differ on sign bit, it's -INF + INF
231  beq LOCAL_LABEL(a_is_nan)
232  pop {r4, r5, r6, r7, pc}
233
234LOCAL_LABEL(a_is_rational):
235  cmp r3, r4
236  bne LOCAL_LABEL(b_is_rational)
237  movs r0, r1
238  pop {r4, r5, r6, r7, pc}
239
240LOCAL_LABEL(b_is_rational):
241  // either a or b or both are zero.
242  adds r4, r2, r3
243  beq  LOCAL_LABEL(both_zero)
244  cmp r2, #0 // is absA 0 ?
245  beq LOCAL_LABEL(ret_b)
246  pop {r4, r5, r6, r7, pc}
247
248LOCAL_LABEL(both_zero):
249  ands r0, r1 // +0 + -0 = +0
250  pop {r4, r5, r6, r7, pc}
251
252LOCAL_LABEL(ret_b):
253  movs r0, r1
254
255LOCAL_LABEL(ret):
256  pop {r4, r5, r6, r7, pc}
257
258LOCAL_LABEL(b_is_nan):
259  movs r0, r1
260LOCAL_LABEL(a_is_nan):
261  movs r1, #1
262  lsls r1, r1, #(significandBits -1) // r1 is quiet bit.
263  orrs r0, r1
264  pop {r4, r5, r6, r7, pc}
265
266LOCAL_LABEL(ret_inf):
267  movs r4, #0xFF
268  lsls r4, r4, #(significandBits)
269  orrs r0, r4
270  lsrs r0, r0, #(significandBits)
271  lsls r0, r0, #(significandBits)
272  pop {r4, r5, r6, r7, pc}
273
274
275END_COMPILERRT_FUNCTION(__addsf3)
276
277NO_EXEC_STACK_DIRECTIVE
278