]>
Commit | Line | Data |
---|---|---|
4202ce82 RE |
1 | /* ieee754-sf.S single-precision floating point support for ARM |
2 | ||
748086b7 | 3 | Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc. |
4202ce82 RE |
4 | Contributed by Nicolas Pitre (nico@cam.org) |
5 | ||
6 | This file is free software; you can redistribute it and/or modify it | |
7 | under the terms of the GNU General Public License as published by the | |
748086b7 | 8 | Free Software Foundation; either version 3, or (at your option) any |
4202ce82 RE |
9 | later version. |
10 | ||
4202ce82 RE |
11 | This file is distributed in the hope that it will be useful, but |
12 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | General Public License for more details. | |
15 | ||
748086b7 JJ |
16 | Under Section 7 of GPL version 3, you are granted additional |
17 | permissions described in the GCC Runtime Library Exception, version | |
18 | 3.1, as published by the Free Software Foundation. | |
19 | ||
20 | You should have received a copy of the GNU General Public License and | |
21 | a copy of the GCC Runtime Library Exception along with this program; | |
22 | see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
23 | <http://www.gnu.org/licenses/>. */ | |
4202ce82 RE |
24 | |
25 | /* | |
26 | * Notes: | |
27 | * | |
28 | * The goal of this code is to be as fast as possible. This is | |
29 | * not meant to be easy to understand for the casual reader. | |
30 | * | |
31 | * Only the default rounding mode is intended for best performances. | |
32 | * Exceptions aren't supported yet, but that can be added quite easily | |
33 | * if necessary without impacting performances. | |
34 | */ | |
35 | ||
bf98ec6c | 36 | #ifdef L_arm_negsf2 |
4202ce82 | 37 | |
496b84c8 | 38 | ARM_FUNC_START negsf2 |
b3f8d95d | 39 | ARM_FUNC_ALIAS aeabi_fneg negsf2 |
6883a666 | 40 | |
496b84c8 RE |
41 | eor r0, r0, #0x80000000 @ flip sign bit |
42 | RET | |
4202ce82 | 43 | |
b3f8d95d | 44 | FUNC_END aeabi_fneg |
496b84c8 | 45 | FUNC_END negsf2 |
4202ce82 | 46 | |
4202ce82 RE |
47 | #endif |
48 | ||
bf98ec6c | 49 | #ifdef L_arm_addsubsf3 |
4202ce82 | 50 | |
b3f8d95d MM |
51 | ARM_FUNC_START aeabi_frsub |
52 | ||
53 | eor r0, r0, #0x80000000 @ flip sign bit of first arg | |
6883a666 NP |
54 | b 1f |
55 | ||
4202ce82 | 56 | ARM_FUNC_START subsf3 |
b3f8d95d | 57 | ARM_FUNC_ALIAS aeabi_fsub subsf3 |
6883a666 | 58 | |
4202ce82 | 59 | eor r1, r1, #0x80000000 @ flip sign bit of second arg |
4c5f9898 | 60 | #if defined(__INTERWORKING_STUBS__) |
4202ce82 RE |
61 | b 1f @ Skip Thumb-code prologue |
62 | #endif | |
63 | ||
64 | ARM_FUNC_START addsf3 | |
b3f8d95d | 65 | ARM_FUNC_ALIAS aeabi_fadd addsf3 |
4202ce82 | 66 | |
6883a666 NP |
67 | 1: @ Look for zeroes, equal values, INF, or NAN. |
68 | movs r2, r0, lsl #1 | |
5b3e6663 PB |
69 | do_it ne, ttt |
70 | COND(mov,s,ne) r3, r1, lsl #1 | |
6883a666 | 71 | teqne r2, r3 |
5b3e6663 PB |
72 | COND(mvn,s,ne) ip, r2, asr #24 |
73 | COND(mvn,s,ne) ip, r3, asr #24 | |
6883a666 | 74 | beq LSYM(Lad_s) |
4202ce82 RE |
75 | |
76 | @ Compute exponent difference. Make largest exponent in r2, | |
77 | @ corresponding arg in r0, and positive exponent difference in r3. | |
6883a666 NP |
78 | mov r2, r2, lsr #24 |
79 | rsbs r3, r2, r3, lsr #24 | |
5b3e6663 | 80 | do_it gt, ttt |
4202ce82 RE |
81 | addgt r2, r2, r3 |
82 | eorgt r1, r0, r1 | |
83 | eorgt r0, r1, r0 | |
84 | eorgt r1, r0, r1 | |
5b3e6663 | 85 | do_it lt |
4202ce82 RE |
86 | rsblt r3, r3, #0 |
87 | ||
88 | @ If exponent difference is too large, return largest argument | |
89 | @ already in r0. We need up to 25 bit to handle proper rounding | |
90 | @ of 0x1p25 - 1.1. | |
6883a666 | 91 | cmp r3, #25 |
5b3e6663 | 92 | do_it hi |
4202ce82 RE |
93 | RETc(hi) |
94 | ||
95 | @ Convert mantissa to signed integer. | |
96 | tst r0, #0x80000000 | |
97 | orr r0, r0, #0x00800000 | |
98 | bic r0, r0, #0xff000000 | |
5b3e6663 | 99 | do_it ne |
4202ce82 RE |
100 | rsbne r0, r0, #0 |
101 | tst r1, #0x80000000 | |
102 | orr r1, r1, #0x00800000 | |
103 | bic r1, r1, #0xff000000 | |
5b3e6663 | 104 | do_it ne |
4202ce82 RE |
105 | rsbne r1, r1, #0 |
106 | ||
107 | @ If exponent == difference, one or both args were denormalized. | |
108 | @ Since this is not common case, rescale them off line. | |
109 | teq r2, r3 | |
110 | beq LSYM(Lad_d) | |
111 | LSYM(Lad_x): | |
112 | ||
6883a666 NP |
113 | @ Compensate for the exponent overlapping the mantissa MSB added later |
114 | sub r2, r2, #1 | |
4202ce82 | 115 | |
6883a666 NP |
116 | @ Shift and add second arg to first arg in r0. |
117 | @ Keep leftover bits into r1. | |
5b3e6663 | 118 | shiftop adds r0 r0 r1 asr r3 ip |
4202ce82 | 119 | rsb r3, r3, #32 |
5b3e6663 | 120 | shift1 lsl, r1, r1, r3 |
4202ce82 | 121 | |
6883a666 NP |
122 | @ Keep absolute value in r0-r1, sign in r3 (the n bit was set above) |
123 | and r3, r0, #0x80000000 | |
4202ce82 | 124 | bpl LSYM(Lad_p) |
5b3e6663 PB |
125 | #if defined(__thumb2__) |
126 | negs r1, r1 | |
127 | sbc r0, r0, r0, lsl #1 | |
128 | #else | |
4202ce82 RE |
129 | rsbs r1, r1, #0 |
130 | rsc r0, r0, #0 | |
5b3e6663 | 131 | #endif |
4202ce82 RE |
132 | |
133 | @ Determine how to normalize the result. | |
134 | LSYM(Lad_p): | |
135 | cmp r0, #0x00800000 | |
6883a666 | 136 | bcc LSYM(Lad_a) |
4202ce82 | 137 | cmp r0, #0x01000000 |
6883a666 | 138 | bcc LSYM(Lad_e) |
4202ce82 RE |
139 | |
140 | @ Result needs to be shifted right. | |
141 | movs r0, r0, lsr #1 | |
142 | mov r1, r1, rrx | |
6883a666 | 143 | add r2, r2, #1 |
4202ce82 RE |
144 | |
145 | @ Make sure we did not bust our exponent. | |
6883a666 NP |
146 | cmp r2, #254 |
147 | bhs LSYM(Lad_o) | |
4202ce82 | 148 | |
6883a666 | 149 | @ Our result is now properly aligned into r0, remaining bits in r1. |
4202ce82 | 150 | @ Pack final result together. |
6883a666 NP |
151 | @ Round with MSB of r1. If halfway between two numbers, round towards |
152 | @ LSB of r0 = 0. | |
4202ce82 | 153 | LSYM(Lad_e): |
6883a666 NP |
154 | cmp r1, #0x80000000 |
155 | adc r0, r0, r2, lsl #23 | |
5b3e6663 | 156 | do_it eq |
6883a666 | 157 | biceq r0, r0, #1 |
4202ce82 RE |
158 | orr r0, r0, r3 |
159 | RET | |
160 | ||
6883a666 NP |
161 | @ Result must be shifted left and exponent adjusted. |
162 | LSYM(Lad_a): | |
163 | movs r1, r1, lsl #1 | |
164 | adc r0, r0, r0 | |
165 | tst r0, #0x00800000 | |
166 | sub r2, r2, #1 | |
167 | bne LSYM(Lad_e) | |
168 | ||
169 | @ No rounding necessary since r1 will always be 0 at this point. | |
4202ce82 RE |
170 | LSYM(Lad_l): |
171 | ||
172 | #if __ARM_ARCH__ < 5 | |
173 | ||
174 | movs ip, r0, lsr #12 | |
175 | moveq r0, r0, lsl #12 | |
6883a666 | 176 | subeq r2, r2, #12 |
4202ce82 RE |
177 | tst r0, #0x00ff0000 |
178 | moveq r0, r0, lsl #8 | |
6883a666 | 179 | subeq r2, r2, #8 |
4202ce82 RE |
180 | tst r0, #0x00f00000 |
181 | moveq r0, r0, lsl #4 | |
6883a666 | 182 | subeq r2, r2, #4 |
4202ce82 RE |
183 | tst r0, #0x00c00000 |
184 | moveq r0, r0, lsl #2 | |
6883a666 NP |
185 | subeq r2, r2, #2 |
186 | cmp r0, #0x00800000 | |
187 | movcc r0, r0, lsl #1 | |
188 | sbcs r2, r2, #0 | |
4202ce82 RE |
189 | |
190 | #else | |
191 | ||
192 | clz ip, r0 | |
193 | sub ip, ip, #8 | |
6883a666 | 194 | subs r2, r2, ip |
5b3e6663 | 195 | shift1 lsl, r0, r0, ip |
4202ce82 RE |
196 | |
197 | #endif | |
198 | ||
6883a666 NP |
199 | @ Final result with sign |
200 | @ If exponent negative, denormalize result. | |
5b3e6663 | 201 | do_it ge, et |
6883a666 NP |
202 | addge r0, r0, r2, lsl #23 |
203 | rsblt r2, r2, #0 | |
204 | orrge r0, r0, r3 | |
5b3e6663 PB |
205 | #if defined(__thumb2__) |
206 | do_it lt, t | |
207 | lsrlt r0, r0, r2 | |
208 | orrlt r0, r3, r0 | |
209 | #else | |
6883a666 | 210 | orrlt r0, r3, r0, lsr r2 |
5b3e6663 | 211 | #endif |
4202ce82 RE |
212 | RET |
213 | ||
214 | @ Fixup and adjust bit position for denormalized arguments. | |
215 | @ Note that r2 must not remain equal to 0. | |
216 | LSYM(Lad_d): | |
217 | teq r2, #0 | |
4202ce82 | 218 | eor r1, r1, #0x00800000 |
5b3e6663 | 219 | do_it eq, te |
6883a666 NP |
220 | eoreq r0, r0, #0x00800000 |
221 | addeq r2, r2, #1 | |
222 | subne r3, r3, #1 | |
4202ce82 RE |
223 | b LSYM(Lad_x) |
224 | ||
6883a666 NP |
225 | LSYM(Lad_s): |
226 | mov r3, r1, lsl #1 | |
227 | ||
228 | mvns ip, r2, asr #24 | |
5b3e6663 PB |
229 | do_it ne |
230 | COND(mvn,s,ne) ip, r3, asr #24 | |
6883a666 NP |
231 | beq LSYM(Lad_i) |
232 | ||
233 | teq r2, r3 | |
234 | beq 1f | |
235 | ||
236 | @ Result is x + 0.0 = x or 0.0 + y = y. | |
237 | teq r2, #0 | |
5b3e6663 | 238 | do_it eq |
6883a666 NP |
239 | moveq r0, r1 |
240 | RET | |
241 | ||
242 | 1: teq r0, r1 | |
243 | ||
244 | @ Result is x - x = 0. | |
5b3e6663 | 245 | do_it ne, t |
4202ce82 | 246 | movne r0, #0 |
6883a666 NP |
247 | RETc(ne) |
248 | ||
249 | @ Result is x + x = 2x. | |
250 | tst r2, #0xff000000 | |
251 | bne 2f | |
252 | movs r0, r0, lsl #1 | |
5b3e6663 | 253 | do_it cs |
6883a666 | 254 | orrcs r0, r0, #0x80000000 |
4202ce82 | 255 | RET |
6883a666 | 256 | 2: adds r2, r2, #(2 << 24) |
5b3e6663 | 257 | do_it cc, t |
6883a666 NP |
258 | addcc r0, r0, #(1 << 23) |
259 | RETc(cc) | |
260 | and r3, r0, #0x80000000 | |
4202ce82 RE |
261 | |
262 | @ Overflow: return INF. | |
263 | LSYM(Lad_o): | |
264 | orr r0, r3, #0x7f000000 | |
265 | orr r0, r0, #0x00800000 | |
266 | RET | |
267 | ||
268 | @ At least one of r0/r1 is INF/NAN. | |
269 | @ if r0 != INF/NAN: return r1 (which is INF/NAN) | |
270 | @ if r1 != INF/NAN: return r0 (which is INF/NAN) | |
271 | @ if r0 or r1 is NAN: return NAN | |
272 | @ if opposite sign: return NAN | |
6883a666 | 273 | @ otherwise return r0 (which is INF or -INF) |
4202ce82 | 274 | LSYM(Lad_i): |
6883a666 | 275 | mvns r2, r2, asr #24 |
5b3e6663 | 276 | do_it ne, et |
4202ce82 | 277 | movne r0, r1 |
5b3e6663 | 278 | COND(mvn,s,eq) r3, r3, asr #24 |
6883a666 | 279 | movne r1, r0 |
4202ce82 | 280 | movs r2, r0, lsl #9 |
5b3e6663 PB |
281 | do_it eq, te |
282 | COND(mov,s,eq) r3, r1, lsl #9 | |
4202ce82 | 283 | teqeq r0, r1 |
6883a666 | 284 | orrne r0, r0, #0x00400000 @ quiet NAN |
4202ce82 RE |
285 | RET |
286 | ||
b3f8d95d MM |
287 | FUNC_END aeabi_frsub |
288 | FUNC_END aeabi_fadd | |
496b84c8 | 289 | FUNC_END addsf3 |
b3f8d95d | 290 | FUNC_END aeabi_fsub |
496b84c8 | 291 | FUNC_END subsf3 |
4202ce82 RE |
292 | |
293 | ARM_FUNC_START floatunsisf | |
b3f8d95d MM |
294 | ARM_FUNC_ALIAS aeabi_ui2f floatunsisf |
295 | ||
4202ce82 RE |
296 | mov r3, #0 |
297 | b 1f | |
298 | ||
299 | ARM_FUNC_START floatsisf | |
b3f8d95d MM |
300 | ARM_FUNC_ALIAS aeabi_i2f floatsisf |
301 | ||
4202ce82 | 302 | ands r3, r0, #0x80000000 |
5b3e6663 | 303 | do_it mi |
4202ce82 RE |
304 | rsbmi r0, r0, #0 |
305 | ||
6883a666 | 306 | 1: movs ip, r0 |
5b3e6663 | 307 | do_it eq |
4202ce82 RE |
308 | RETc(eq) |
309 | ||
6883a666 NP |
310 | @ Add initial exponent to sign |
311 | orr r3, r3, #((127 + 23) << 23) | |
312 | ||
313 | .ifnc ah, r0 | |
314 | mov ah, r0 | |
315 | .endif | |
316 | mov al, #0 | |
317 | b 2f | |
4202ce82 | 318 | |
b3f8d95d | 319 | FUNC_END aeabi_i2f |
496b84c8 | 320 | FUNC_END floatsisf |
b3f8d95d | 321 | FUNC_END aeabi_ui2f |
496b84c8 RE |
322 | FUNC_END floatunsisf |
323 | ||
0a1aa867 RE |
324 | ARM_FUNC_START floatundisf |
325 | ARM_FUNC_ALIAS aeabi_ul2f floatundisf | |
6883a666 | 326 | |
0a1aa867 RE |
327 | orrs r2, r0, r1 |
328 | #if !defined (__VFP_FP__) && !defined(__SOFTFP__) | |
27e03cf1 | 329 | do_it eq, t |
0a1aa867 | 330 | mvfeqs f0, #0.0 |
5b3e6663 PB |
331 | #else |
332 | do_it eq | |
0a1aa867 RE |
333 | #endif |
334 | RETc(eq) | |
0a1aa867 RE |
335 | |
336 | mov r3, #0 | |
6883a666 | 337 | b 1f |
0a1aa867 RE |
338 | |
339 | ARM_FUNC_START floatdisf | |
340 | ARM_FUNC_ALIAS aeabi_l2f floatdisf | |
341 | ||
342 | orrs r2, r0, r1 | |
343 | #if !defined (__VFP_FP__) && !defined(__SOFTFP__) | |
5b3e6663 | 344 | do_it eq, t |
0a1aa867 | 345 | mvfeqs f0, #0.0 |
5b3e6663 PB |
346 | #else |
347 | do_it eq | |
0a1aa867 RE |
348 | #endif |
349 | RETc(eq) | |
6883a666 NP |
350 | |
351 | ands r3, ah, #0x80000000 @ sign bit in r3 | |
352 | bpl 1f | |
5b3e6663 PB |
353 | #if defined(__thumb2__) |
354 | negs al, al | |
355 | sbc ah, ah, ah, lsl #1 | |
356 | #else | |
6883a666 NP |
357 | rsbs al, al, #0 |
358 | rsc ah, ah, #0 | |
5b3e6663 | 359 | #endif |
6883a666 | 360 | 1: |
0a1aa867 RE |
361 | #if !defined (__VFP_FP__) && !defined(__SOFTFP__) |
362 | @ For hard FPA code we want to return via the tail below so that | |
363 | @ we can return the result in f0 as well as in r0 for backwards | |
364 | @ compatibility. | |
f825b328 | 365 | str lr, [sp, #-8]! |
6883a666 | 366 | adr lr, LSYM(f0_ret) |
0a1aa867 | 367 | #endif |
6883a666 | 368 | |
0a1aa867 | 369 | movs ip, ah |
5b3e6663 | 370 | do_it eq, tt |
6883a666 | 371 | moveq ip, al |
3188a512 NP |
372 | moveq ah, al |
373 | moveq al, #0 | |
6883a666 NP |
374 | |
375 | @ Add initial exponent to sign | |
376 | orr r3, r3, #((127 + 23 + 32) << 23) | |
5b3e6663 | 377 | do_it eq |
6883a666 NP |
378 | subeq r3, r3, #(32 << 23) |
379 | 2: sub r3, r3, #(1 << 23) | |
0a1aa867 RE |
380 | |
381 | #if __ARM_ARCH__ < 5 | |
6883a666 NP |
382 | |
383 | mov r2, #23 | |
384 | cmp ip, #(1 << 16) | |
5b3e6663 | 385 | do_it hs, t |
6883a666 NP |
386 | movhs ip, ip, lsr #16 |
387 | subhs r2, r2, #16 | |
388 | cmp ip, #(1 << 8) | |
5b3e6663 | 389 | do_it hs, t |
6883a666 NP |
390 | movhs ip, ip, lsr #8 |
391 | subhs r2, r2, #8 | |
392 | cmp ip, #(1 << 4) | |
5b3e6663 | 393 | do_it hs, t |
6883a666 NP |
394 | movhs ip, ip, lsr #4 |
395 | subhs r2, r2, #4 | |
396 | cmp ip, #(1 << 2) | |
5b3e6663 | 397 | do_it hs, e |
6883a666 NP |
398 | subhs r2, r2, #2 |
399 | sublo r2, r2, ip, lsr #1 | |
400 | subs r2, r2, ip, lsr #3 | |
401 | ||
0a1aa867 | 402 | #else |
6883a666 NP |
403 | |
404 | clz r2, ip | |
405 | subs r2, r2, #8 | |
406 | ||
0a1aa867 | 407 | #endif |
6883a666 NP |
408 | |
409 | sub r3, r3, r2, lsl #23 | |
410 | blt 3f | |
411 | ||
5b3e6663 PB |
412 | shiftop add r3 r3 ah lsl r2 ip |
413 | shift1 lsl, ip, al, r2 | |
6883a666 NP |
414 | rsb r2, r2, #32 |
415 | cmp ip, #0x80000000 | |
5b3e6663 PB |
416 | shiftop adc r0 r3 al lsr r2 r2 |
417 | do_it eq | |
6883a666 NP |
418 | biceq r0, r0, #1 |
419 | RET | |
420 | ||
421 | 3: add r2, r2, #32 | |
5b3e6663 | 422 | shift1 lsl, ip, ah, r2 |
6883a666 NP |
423 | rsb r2, r2, #32 |
424 | orrs al, al, ip, lsl #1 | |
5b3e6663 PB |
425 | shiftop adc r0 r3 ah lsr r2 r2 |
426 | do_it eq | |
6883a666 NP |
427 | biceq r0, r0, ip, lsr #31 |
428 | RET | |
429 | ||
0a1aa867 | 430 | #if !defined (__VFP_FP__) && !defined(__SOFTFP__) |
6883a666 | 431 | |
8cd0dbef | 432 | LSYM(f0_ret): |
0a1aa867 RE |
433 | str r0, [sp, #-4]! |
434 | ldfs f0, [sp], #4 | |
435 | RETLDM | |
6883a666 | 436 | |
0a1aa867 | 437 | #endif |
6883a666 | 438 | |
0a1aa867 RE |
439 | FUNC_END floatdisf |
440 | FUNC_END aeabi_l2f | |
441 | FUNC_END floatundisf | |
442 | FUNC_END aeabi_ul2f | |
443 | ||
496b84c8 RE |
444 | #endif /* L_addsubsf3 */ |
445 | ||
bf98ec6c | 446 | #ifdef L_arm_muldivsf3 |
4202ce82 RE |
447 | |
448 | ARM_FUNC_START mulsf3 | |
b3f8d95d | 449 | ARM_FUNC_ALIAS aeabi_fmul mulsf3 |
4202ce82 | 450 | |
6883a666 NP |
451 | @ Mask out exponents, trap any zero/denormal/INF/NAN. |
452 | mov ip, #0xff | |
453 | ands r2, ip, r0, lsr #23 | |
5b3e6663 PB |
454 | do_it ne, tt |
455 | COND(and,s,ne) r3, ip, r1, lsr #23 | |
6883a666 NP |
456 | teqne r2, ip |
457 | teqne r3, ip | |
458 | beq LSYM(Lml_s) | |
4202ce82 | 459 | LSYM(Lml_x): |
4202ce82 | 460 | |
6883a666 NP |
461 | @ Add exponents together |
462 | add r2, r2, r3 | |
463 | ||
464 | @ Determine final sign. | |
465 | eor ip, r0, r1 | |
4202ce82 RE |
466 | |
467 | @ Convert mantissa to unsigned integer. | |
6883a666 NP |
468 | @ If power of two, branch to a separate path. |
469 | @ Make up for final alignment. | |
470 | movs r0, r0, lsl #9 | |
5b3e6663 PB |
471 | do_it ne |
472 | COND(mov,s,ne) r1, r1, lsl #9 | |
6883a666 NP |
473 | beq LSYM(Lml_1) |
474 | mov r3, #0x08000000 | |
475 | orr r0, r3, r0, lsr #5 | |
476 | orr r1, r3, r1, lsr #5 | |
4202ce82 RE |
477 | |
478 | #if __ARM_ARCH__ < 4 | |
479 | ||
6883a666 NP |
480 | @ Put sign bit in r3, which will be restored into r0 later. |
481 | and r3, ip, #0x80000000 | |
482 | ||
4202ce82 | 483 | @ Well, no way to make it shorter without the umull instruction. |
5b3e6663 | 484 | do_push {r3, r4, r5} |
4202ce82 RE |
485 | mov r4, r0, lsr #16 |
486 | mov r5, r1, lsr #16 | |
6883a666 NP |
487 | bic r0, r0, r4, lsl #16 |
488 | bic r1, r1, r5, lsl #16 | |
4202ce82 RE |
489 | mul ip, r4, r5 |
490 | mul r3, r0, r1 | |
491 | mul r0, r5, r0 | |
492 | mla r0, r4, r1, r0 | |
493 | adds r3, r3, r0, lsl #16 | |
6883a666 | 494 | adc r1, ip, r0, lsr #16 |
5b3e6663 | 495 | do_pop {r0, r4, r5} |
4202ce82 RE |
496 | |
497 | #else | |
498 | ||
6883a666 NP |
499 | @ The actual multiplication. |
500 | umull r3, r1, r0, r1 | |
501 | ||
502 | @ Put final sign in r0. | |
503 | and r0, ip, #0x80000000 | |
4202ce82 RE |
504 | |
505 | #endif | |
506 | ||
6883a666 NP |
507 | @ Adjust result upon the MSB position. |
508 | cmp r1, #(1 << 23) | |
5b3e6663 | 509 | do_it cc, tt |
6883a666 NP |
510 | movcc r1, r1, lsl #1 |
511 | orrcc r1, r1, r3, lsr #31 | |
512 | movcc r3, r3, lsl #1 | |
4202ce82 | 513 | |
6883a666 NP |
514 | @ Add sign to result. |
515 | orr r0, r0, r1 | |
4202ce82 | 516 | |
6883a666 NP |
517 | @ Apply exponent bias, check for under/overflow. |
518 | sbc r2, r2, #127 | |
519 | cmp r2, #(254 - 1) | |
520 | bhi LSYM(Lml_u) | |
4202ce82 | 521 | |
6883a666 NP |
522 | @ Round the result, merge final exponent. |
523 | cmp r3, #0x80000000 | |
524 | adc r0, r0, r2, lsl #23 | |
5b3e6663 | 525 | do_it eq |
6883a666 | 526 | biceq r0, r0, #1 |
4202ce82 RE |
527 | RET |
528 | ||
6883a666 NP |
529 | @ Multiplication by 0x1p*: let''s shortcut a lot of code. |
530 | LSYM(Lml_1): | |
531 | teq r0, #0 | |
532 | and ip, ip, #0x80000000 | |
5b3e6663 | 533 | do_it eq |
6883a666 NP |
534 | moveq r1, r1, lsl #9 |
535 | orr r0, ip, r0, lsr #9 | |
536 | orr r0, r0, r1, lsr #9 | |
537 | subs r2, r2, #127 | |
5b3e6663 PB |
538 | do_it gt, tt |
539 | COND(rsb,s,gt) r3, r2, #255 | |
6883a666 NP |
540 | orrgt r0, r0, r2, lsl #23 |
541 | RETc(gt) | |
542 | ||
543 | @ Under/overflow: fix things up for the code below. | |
544 | orr r0, r0, #0x00800000 | |
545 | mov r3, #0 | |
546 | subs r2, r2, #1 | |
4202ce82 | 547 | |
4202ce82 | 548 | LSYM(Lml_u): |
6883a666 NP |
549 | @ Overflow? |
550 | bgt LSYM(Lml_o) | |
4202ce82 | 551 | |
6883a666 NP |
552 | @ Check if denormalized result is possible, otherwise return signed 0. |
553 | cmn r2, #(24 + 1) | |
5b3e6663 | 554 | do_it le, t |
6883a666 NP |
555 | bicle r0, r0, #0x7fffffff |
556 | RETc(le) | |
4202ce82 RE |
557 | |
558 | @ Shift value right, round, etc. | |
6883a666 NP |
559 | rsb r2, r2, #0 |
560 | movs r1, r0, lsl #1 | |
5b3e6663 | 561 | shift1 lsr, r1, r1, r2 |
6883a666 | 562 | rsb r2, r2, #32 |
5b3e6663 | 563 | shift1 lsl, ip, r0, r2 |
6883a666 | 564 | movs r0, r1, rrx |
4202ce82 | 565 | adc r0, r0, #0 |
6883a666 | 566 | orrs r3, r3, ip, lsl #1 |
5b3e6663 | 567 | do_it eq |
6883a666 | 568 | biceq r0, r0, ip, lsr #31 |
4202ce82 RE |
569 | RET |
570 | ||
571 | @ One or both arguments are denormalized. | |
572 | @ Scale them leftwards and preserve sign bit. | |
573 | LSYM(Lml_d): | |
574 | teq r2, #0 | |
575 | and ip, r0, #0x80000000 | |
5b3e6663 PB |
576 | 1: do_it eq, tt |
577 | moveq r0, r0, lsl #1 | |
4202ce82 | 578 | tsteq r0, #0x00800000 |
6883a666 | 579 | subeq r2, r2, #1 |
4202ce82 RE |
580 | beq 1b |
581 | orr r0, r0, ip | |
582 | teq r3, #0 | |
583 | and ip, r1, #0x80000000 | |
5b3e6663 PB |
584 | 2: do_it eq, tt |
585 | moveq r1, r1, lsl #1 | |
4202ce82 | 586 | tsteq r1, #0x00800000 |
6883a666 | 587 | subeq r3, r3, #1 |
4202ce82 RE |
588 | beq 2b |
589 | orr r1, r1, ip | |
590 | b LSYM(Lml_x) | |
591 | ||
4202ce82 | 592 | LSYM(Lml_s): |
6883a666 NP |
593 | @ Isolate the INF and NAN cases away |
594 | and r3, ip, r1, lsr #23 | |
595 | teq r2, ip | |
5b3e6663 | 596 | do_it ne |
6883a666 NP |
597 | teqne r3, ip |
598 | beq 1f | |
599 | ||
600 | @ Here, one or more arguments are either denormalized or zero. | |
601 | bics ip, r0, #0x80000000 | |
5b3e6663 PB |
602 | do_it ne |
603 | COND(bic,s,ne) ip, r1, #0x80000000 | |
6883a666 NP |
604 | bne LSYM(Lml_d) |
605 | ||
606 | @ Result is 0, but determine sign anyway. | |
607 | LSYM(Lml_z): | |
608 | eor r0, r0, r1 | |
609 | bic r0, r0, #0x7fffffff | |
610 | RET | |
611 | ||
612 | 1: @ One or both args are INF or NAN. | |
4202ce82 | 613 | teq r0, #0x0 |
5b3e6663 | 614 | do_it ne, ett |
4202ce82 | 615 | teqne r0, #0x80000000 |
6883a666 NP |
616 | moveq r0, r1 |
617 | teqne r1, #0x0 | |
4202ce82 RE |
618 | teqne r1, #0x80000000 |
619 | beq LSYM(Lml_n) @ 0 * INF or INF * 0 -> NAN | |
6883a666 | 620 | teq r2, ip |
4202ce82 RE |
621 | bne 1f |
622 | movs r2, r0, lsl #9 | |
623 | bne LSYM(Lml_n) @ NAN * <anything> -> NAN | |
6883a666 | 624 | 1: teq r3, ip |
4202ce82 RE |
625 | bne LSYM(Lml_i) |
626 | movs r3, r1, lsl #9 | |
5b3e6663 | 627 | do_it ne |
6883a666 | 628 | movne r0, r1 |
4202ce82 RE |
629 | bne LSYM(Lml_n) @ <anything> * NAN -> NAN |
630 | ||
631 | @ Result is INF, but we need to determine its sign. | |
632 | LSYM(Lml_i): | |
633 | eor r0, r0, r1 | |
634 | ||
635 | @ Overflow: return INF (sign already in r0). | |
636 | LSYM(Lml_o): | |
637 | and r0, r0, #0x80000000 | |
638 | orr r0, r0, #0x7f000000 | |
639 | orr r0, r0, #0x00800000 | |
640 | RET | |
641 | ||
6883a666 | 642 | @ Return a quiet NAN. |
4202ce82 | 643 | LSYM(Lml_n): |
6883a666 | 644 | orr r0, r0, #0x7f000000 |
4202ce82 RE |
645 | orr r0, r0, #0x00c00000 |
646 | RET | |
647 | ||
b3f8d95d | 648 | FUNC_END aeabi_fmul |
496b84c8 | 649 | FUNC_END mulsf3 |
4202ce82 RE |
650 | |
651 | ARM_FUNC_START divsf3 | |
b3f8d95d | 652 | ARM_FUNC_ALIAS aeabi_fdiv divsf3 |
4202ce82 | 653 | |
6883a666 NP |
654 | @ Mask out exponents, trap any zero/denormal/INF/NAN. |
655 | mov ip, #0xff | |
656 | ands r2, ip, r0, lsr #23 | |
5b3e6663 PB |
657 | do_it ne, tt |
658 | COND(and,s,ne) r3, ip, r1, lsr #23 | |
6883a666 NP |
659 | teqne r2, ip |
660 | teqne r3, ip | |
661 | beq LSYM(Ldv_s) | |
4202ce82 | 662 | LSYM(Ldv_x): |
6883a666 NP |
663 | |
664 | @ Substract divisor exponent from dividend''s | |
665 | sub r2, r2, r3 | |
4202ce82 RE |
666 | |
667 | @ Preserve final sign into ip. | |
668 | eor ip, r0, r1 | |
669 | ||
670 | @ Convert mantissa to unsigned integer. | |
671 | @ Dividend -> r3, divisor -> r1. | |
4202ce82 RE |
672 | movs r1, r1, lsl #9 |
673 | mov r0, r0, lsl #9 | |
674 | beq LSYM(Ldv_1) | |
6883a666 | 675 | mov r3, #0x10000000 |
4202ce82 RE |
676 | orr r1, r3, r1, lsr #4 |
677 | orr r3, r3, r0, lsr #4 | |
678 | ||
679 | @ Initialize r0 (result) with final sign bit. | |
680 | and r0, ip, #0x80000000 | |
681 | ||
682 | @ Ensure result will land to known bit position. | |
6883a666 | 683 | @ Apply exponent bias accordingly. |
4202ce82 | 684 | cmp r3, r1 |
5b3e6663 | 685 | do_it cc |
4202ce82 | 686 | movcc r3, r3, lsl #1 |
6883a666 | 687 | adc r2, r2, #(127 - 2) |
4202ce82 RE |
688 | |
689 | @ The actual division loop. | |
690 | mov ip, #0x00800000 | |
691 | 1: cmp r3, r1 | |
5b3e6663 | 692 | do_it cs, t |
4202ce82 RE |
693 | subcs r3, r3, r1 |
694 | orrcs r0, r0, ip | |
695 | cmp r3, r1, lsr #1 | |
5b3e6663 | 696 | do_it cs, t |
4202ce82 RE |
697 | subcs r3, r3, r1, lsr #1 |
698 | orrcs r0, r0, ip, lsr #1 | |
699 | cmp r3, r1, lsr #2 | |
5b3e6663 | 700 | do_it cs, t |
4202ce82 RE |
701 | subcs r3, r3, r1, lsr #2 |
702 | orrcs r0, r0, ip, lsr #2 | |
703 | cmp r3, r1, lsr #3 | |
5b3e6663 | 704 | do_it cs, t |
4202ce82 RE |
705 | subcs r3, r3, r1, lsr #3 |
706 | orrcs r0, r0, ip, lsr #3 | |
707 | movs r3, r3, lsl #4 | |
5b3e6663 PB |
708 | do_it ne |
709 | COND(mov,s,ne) ip, ip, lsr #4 | |
4202ce82 RE |
710 | bne 1b |
711 | ||
6883a666 NP |
712 | @ Check exponent for under/overflow. |
713 | cmp r2, #(254 - 1) | |
714 | bhi LSYM(Lml_u) | |
4202ce82 | 715 | |
6883a666 | 716 | @ Round the result, merge final exponent. |
4202ce82 | 717 | cmp r3, r1 |
6883a666 | 718 | adc r0, r0, r2, lsl #23 |
5b3e6663 | 719 | do_it eq |
4202ce82 | 720 | biceq r0, r0, #1 |
4202ce82 RE |
721 | RET |
722 | ||
723 | @ Division by 0x1p*: let''s shortcut a lot of code. | |
724 | LSYM(Ldv_1): | |
725 | and ip, ip, #0x80000000 | |
726 | orr r0, ip, r0, lsr #9 | |
6883a666 | 727 | adds r2, r2, #127 |
5b3e6663 PB |
728 | do_it gt, tt |
729 | COND(rsb,s,gt) r3, r2, #255 | |
6883a666 | 730 | orrgt r0, r0, r2, lsl #23 |
4202ce82 | 731 | RETc(gt) |
6883a666 | 732 | |
4202ce82 RE |
733 | orr r0, r0, #0x00800000 |
734 | mov r3, #0 | |
6883a666 NP |
735 | subs r2, r2, #1 |
736 | b LSYM(Lml_u) | |
4202ce82 RE |
737 | |
738 | @ One or both arguments are denormalized. | |
739 | @ Scale them leftwards and preserve sign bit. | |
740 | LSYM(Ldv_d): | |
741 | teq r2, #0 | |
742 | and ip, r0, #0x80000000 | |
5b3e6663 PB |
743 | 1: do_it eq, tt |
744 | moveq r0, r0, lsl #1 | |
4202ce82 | 745 | tsteq r0, #0x00800000 |
6883a666 | 746 | subeq r2, r2, #1 |
4202ce82 RE |
747 | beq 1b |
748 | orr r0, r0, ip | |
749 | teq r3, #0 | |
750 | and ip, r1, #0x80000000 | |
5b3e6663 PB |
751 | 2: do_it eq, tt |
752 | moveq r1, r1, lsl #1 | |
4202ce82 | 753 | tsteq r1, #0x00800000 |
6883a666 | 754 | subeq r3, r3, #1 |
4202ce82 RE |
755 | beq 2b |
756 | orr r1, r1, ip | |
757 | b LSYM(Ldv_x) | |
758 | ||
6883a666 | 759 | @ One or both arguments are either INF, NAN, zero or denormalized. |
4202ce82 | 760 | LSYM(Ldv_s): |
6883a666 NP |
761 | and r3, ip, r1, lsr #23 |
762 | teq r2, ip | |
4202ce82 RE |
763 | bne 1f |
764 | movs r2, r0, lsl #9 | |
765 | bne LSYM(Lml_n) @ NAN / <anything> -> NAN | |
6883a666 NP |
766 | teq r3, ip |
767 | bne LSYM(Lml_i) @ INF / <anything> -> INF | |
768 | mov r0, r1 | |
769 | b LSYM(Lml_n) @ INF / (INF or NAN) -> NAN | |
770 | 1: teq r3, ip | |
4202ce82 RE |
771 | bne 2f |
772 | movs r3, r1, lsl #9 | |
6883a666 NP |
773 | beq LSYM(Lml_z) @ <anything> / INF -> 0 |
774 | mov r0, r1 | |
775 | b LSYM(Lml_n) @ <anything> / NAN -> NAN | |
a4d05547 | 776 | 2: @ If both are nonzero, we need to normalize and resume above. |
6883a666 | 777 | bics ip, r0, #0x80000000 |
5b3e6663 PB |
778 | do_it ne |
779 | COND(bic,s,ne) ip, r1, #0x80000000 | |
6883a666 NP |
780 | bne LSYM(Ldv_d) |
781 | @ One or both arguments are zero. | |
4202ce82 RE |
782 | bics r2, r0, #0x80000000 |
783 | bne LSYM(Lml_i) @ <non_zero> / 0 -> INF | |
784 | bics r3, r1, #0x80000000 | |
785 | bne LSYM(Lml_z) @ 0 / <non_zero> -> 0 | |
786 | b LSYM(Lml_n) @ 0 / 0 -> NAN | |
787 | ||
b3f8d95d | 788 | FUNC_END aeabi_fdiv |
496b84c8 RE |
789 | FUNC_END divsf3 |
790 | ||
791 | #endif /* L_muldivsf3 */ | |
792 | ||
bf98ec6c | 793 | #ifdef L_arm_cmpsf2 |
4202ce82 | 794 | |
b3f8d95d MM |
795 | @ The return value in r0 is |
796 | @ | |
797 | @ 0 if the operands are equal | |
798 | @ 1 if the first operand is greater than the second, or | |
799 | @ the operands are unordered and the operation is | |
800 | @ CMP, LT, LE, NE, or EQ. | |
801 | @ -1 if the first operand is less than the second, or | |
802 | @ the operands are unordered and the operation is GT | |
803 | @ or GE. | |
804 | @ | |
805 | @ The Z flag will be set iff the operands are equal. | |
806 | @ | |
807 | @ The following registers are clobbered by this function: | |
808 | @ ip, r0, r1, r2, r3 | |
809 | ||
4202ce82 | 810 | ARM_FUNC_START gtsf2 |
46049cff | 811 | ARM_FUNC_ALIAS gesf2 gtsf2 |
6883a666 | 812 | mov ip, #-1 |
4202ce82 RE |
813 | b 1f |
814 | ||
4202ce82 | 815 | ARM_FUNC_START ltsf2 |
46049cff | 816 | ARM_FUNC_ALIAS lesf2 ltsf2 |
6883a666 | 817 | mov ip, #1 |
4202ce82 RE |
818 | b 1f |
819 | ||
4202ce82 | 820 | ARM_FUNC_START cmpsf2 |
46049cff RE |
821 | ARM_FUNC_ALIAS nesf2 cmpsf2 |
822 | ARM_FUNC_ALIAS eqsf2 cmpsf2 | |
6883a666 NP |
823 | mov ip, #1 @ how should we specify unordered here? |
824 | ||
b89f8e3c | 825 | 1: str ip, [sp, #-4]! |
6883a666 NP |
826 | |
827 | @ Trap any INF/NAN first. | |
828 | mov r2, r0, lsl #1 | |
829 | mov r3, r1, lsl #1 | |
830 | mvns ip, r2, asr #24 | |
5b3e6663 PB |
831 | do_it ne |
832 | COND(mvn,s,ne) ip, r3, asr #24 | |
4202ce82 RE |
833 | beq 3f |
834 | ||
6883a666 NP |
835 | @ Compare values. |
836 | @ Note that 0.0 is equal to -0.0. | |
b89f8e3c JB |
837 | 2: add sp, sp, #4 |
838 | orrs ip, r2, r3, lsr #1 @ test if both are 0, clear C flag | |
5b3e6663 | 839 | do_it ne |
6883a666 | 840 | teqne r0, r1 @ if not 0 compare sign |
5b3e6663 PB |
841 | do_it pl |
842 | COND(sub,s,pl) r0, r2, r3 @ if same sign compare values, set r0 | |
4202ce82 | 843 | |
6883a666 | 844 | @ Result: |
5b3e6663 | 845 | do_it hi |
6883a666 | 846 | movhi r0, r1, asr #31 |
5b3e6663 | 847 | do_it lo |
6883a666 | 848 | mvnlo r0, r1, asr #31 |
5b3e6663 | 849 | do_it ne |
6883a666 | 850 | orrne r0, r0, #1 |
4202ce82 RE |
851 | RET |
852 | ||
6883a666 NP |
853 | @ Look for a NAN. |
854 | 3: mvns ip, r2, asr #24 | |
4202ce82 | 855 | bne 4f |
4202ce82 | 856 | movs ip, r0, lsl #9 |
6883a666 NP |
857 | bne 5f @ r0 is NAN |
858 | 4: mvns ip, r3, asr #24 | |
859 | bne 2b | |
860 | movs ip, r1, lsl #9 | |
861 | beq 2b @ r1 is not NAN | |
b89f8e3c | 862 | 5: ldr r0, [sp], #4 @ return unordered code. |
4202ce82 RE |
863 | RET |
864 | ||
496b84c8 RE |
865 | FUNC_END gesf2 |
866 | FUNC_END gtsf2 | |
867 | FUNC_END lesf2 | |
868 | FUNC_END ltsf2 | |
869 | FUNC_END nesf2 | |
870 | FUNC_END eqsf2 | |
871 | FUNC_END cmpsf2 | |
872 | ||
b3f8d95d | 873 | ARM_FUNC_START aeabi_cfrcmple |
6883a666 | 874 | |
b3f8d95d MM |
875 | mov ip, r0 |
876 | mov r0, r1 | |
877 | mov r1, ip | |
878 | b 6f | |
6883a666 | 879 | |
b3f8d95d MM |
880 | ARM_FUNC_START aeabi_cfcmpeq |
881 | ARM_FUNC_ALIAS aeabi_cfcmple aeabi_cfcmpeq | |
6883a666 | 882 | |
b3f8d95d MM |
883 | @ The status-returning routines are required to preserve all |
884 | @ registers except ip, lr, and cpsr. | |
5b3e6663 | 885 | 6: do_push {r0, r1, r2, r3, lr} |
b3f8d95d MM |
886 | ARM_CALL cmpsf2 |
887 | @ Set the Z flag correctly, and the C flag unconditionally. | |
5b3e6663 | 888 | cmp r0, #0 |
b3f8d95d MM |
889 | @ Clear the C flag if the return value was -1, indicating |
890 | @ that the first operand was smaller than the second. | |
5b3e6663 PB |
891 | do_it mi |
892 | cmnmi r0, #0 | |
893 | RETLDM "r0, r1, r2, r3" | |
6883a666 | 894 | |
b3f8d95d MM |
895 | FUNC_END aeabi_cfcmple |
896 | FUNC_END aeabi_cfcmpeq | |
6883a666 NP |
897 | FUNC_END aeabi_cfrcmple |
898 | ||
b3f8d95d | 899 | ARM_FUNC_START aeabi_fcmpeq |
6883a666 | 900 | |
f825b328 | 901 | str lr, [sp, #-8]! |
b3f8d95d | 902 | ARM_CALL aeabi_cfcmple |
5b3e6663 | 903 | do_it eq, e |
b3f8d95d MM |
904 | moveq r0, #1 @ Equal to. |
905 | movne r0, #0 @ Less than, greater than, or unordered. | |
906 | RETLDM | |
6883a666 | 907 | |
b3f8d95d MM |
908 | FUNC_END aeabi_fcmpeq |
909 | ||
910 | ARM_FUNC_START aeabi_fcmplt | |
6883a666 | 911 | |
f825b328 | 912 | str lr, [sp, #-8]! |
b3f8d95d | 913 | ARM_CALL aeabi_cfcmple |
5b3e6663 | 914 | do_it cc, e |
b3f8d95d MM |
915 | movcc r0, #1 @ Less than. |
916 | movcs r0, #0 @ Equal to, greater than, or unordered. | |
917 | RETLDM | |
6883a666 | 918 | |
b3f8d95d MM |
919 | FUNC_END aeabi_fcmplt |
920 | ||
921 | ARM_FUNC_START aeabi_fcmple | |
6883a666 | 922 | |
f825b328 | 923 | str lr, [sp, #-8]! |
b3f8d95d | 924 | ARM_CALL aeabi_cfcmple |
5b3e6663 | 925 | do_it ls, e |
b3f8d95d MM |
926 | movls r0, #1 @ Less than or equal to. |
927 | movhi r0, #0 @ Greater than or unordered. | |
928 | RETLDM | |
6883a666 | 929 | |
b3f8d95d MM |
930 | FUNC_END aeabi_fcmple |
931 | ||
932 | ARM_FUNC_START aeabi_fcmpge | |
6883a666 | 933 | |
f825b328 | 934 | str lr, [sp, #-8]! |
b3f8d95d | 935 | ARM_CALL aeabi_cfrcmple |
5b3e6663 | 936 | do_it ls, e |
b3f8d95d MM |
937 | movls r0, #1 @ Operand 2 is less than or equal to operand 1. |
938 | movhi r0, #0 @ Operand 2 greater than operand 1, or unordered. | |
939 | RETLDM | |
6883a666 | 940 | |
b3f8d95d MM |
941 | FUNC_END aeabi_fcmpge |
942 | ||
943 | ARM_FUNC_START aeabi_fcmpgt | |
6883a666 | 944 | |
f825b328 | 945 | str lr, [sp, #-8]! |
b3f8d95d | 946 | ARM_CALL aeabi_cfrcmple |
5b3e6663 | 947 | do_it cc, e |
b3f8d95d MM |
948 | movcc r0, #1 @ Operand 2 is less than operand 1. |
949 | movcs r0, #0 @ Operand 2 is greater than or equal to operand 1, | |
950 | @ or they are unordered. | |
951 | RETLDM | |
6883a666 | 952 | |
b3f8d95d | 953 | FUNC_END aeabi_fcmpgt |
6883a666 | 954 | |
496b84c8 RE |
955 | #endif /* L_cmpsf2 */ |
956 | ||
bf98ec6c | 957 | #ifdef L_arm_unordsf2 |
4202ce82 RE |
958 | |
959 | ARM_FUNC_START unordsf2 | |
b3f8d95d | 960 | ARM_FUNC_ALIAS aeabi_fcmpun unordsf2 |
6883a666 NP |
961 | |
962 | mov r2, r0, lsl #1 | |
963 | mov r3, r1, lsl #1 | |
964 | mvns ip, r2, asr #24 | |
4202ce82 | 965 | bne 1f |
6883a666 | 966 | movs ip, r0, lsl #9 |
4202ce82 | 967 | bne 3f @ r0 is NAN |
6883a666 NP |
968 | 1: mvns ip, r3, asr #24 |
969 | bne 2f | |
970 | movs ip, r1, lsl #9 | |
971 | bne 3f @ r1 is NAN | |
4202ce82 RE |
972 | 2: mov r0, #0 @ arguments are ordered. |
973 | RET | |
974 | 3: mov r0, #1 @ arguments are unordered. | |
975 | RET | |
976 | ||
b3f8d95d | 977 | FUNC_END aeabi_fcmpun |
496b84c8 RE |
978 | FUNC_END unordsf2 |
979 | ||
980 | #endif /* L_unordsf2 */ | |
981 | ||
bf98ec6c | 982 | #ifdef L_arm_fixsfsi |
4202ce82 RE |
983 | |
984 | ARM_FUNC_START fixsfsi | |
b3f8d95d | 985 | ARM_FUNC_ALIAS aeabi_f2iz fixsfsi |
4202ce82 RE |
986 | |
987 | @ check exponent range. | |
6883a666 | 988 | mov r2, r0, lsl #1 |
4202ce82 | 989 | cmp r2, #(127 << 24) |
6883a666 NP |
990 | bcc 1f @ value is too small |
991 | mov r3, #(127 + 31) | |
992 | subs r2, r3, r2, lsr #24 | |
993 | bls 2f @ value is too large | |
994 | ||
995 | @ scale value | |
996 | mov r3, r0, lsl #8 | |
997 | orr r3, r3, #0x80000000 | |
998 | tst r0, #0x80000000 @ the sign bit | |
5b3e6663 PB |
999 | shift1 lsr, r0, r3, r2 |
1000 | do_it ne | |
4202ce82 RE |
1001 | rsbne r0, r0, #0 |
1002 | RET | |
1003 | ||
6883a666 NP |
1004 | 1: mov r0, #0 |
1005 | RET | |
1006 | ||
1007 | 2: cmp r2, #(127 + 31 - 0xff) | |
1008 | bne 3f | |
1009 | movs r2, r0, lsl #9 | |
1010 | bne 4f @ r0 is NAN. | |
1011 | 3: ands r0, r0, #0x80000000 @ the sign bit | |
5b3e6663 | 1012 | do_it eq |
4202ce82 | 1013 | moveq r0, #0x7fffffff @ the maximum signed positive si |
4202ce82 RE |
1014 | RET |
1015 | ||
6883a666 | 1016 | 4: mov r0, #0 @ What should we convert NAN to? |
4202ce82 RE |
1017 | RET |
1018 | ||
b3f8d95d | 1019 | FUNC_END aeabi_f2iz |
496b84c8 RE |
1020 | FUNC_END fixsfsi |
1021 | ||
1022 | #endif /* L_fixsfsi */ | |
1023 | ||
bf98ec6c | 1024 | #ifdef L_arm_fixunssfsi |
4202ce82 RE |
1025 | |
1026 | ARM_FUNC_START fixunssfsi | |
b3f8d95d | 1027 | ARM_FUNC_ALIAS aeabi_f2uiz fixunssfsi |
4202ce82 RE |
1028 | |
1029 | @ check exponent range. | |
6883a666 NP |
1030 | movs r2, r0, lsl #1 |
1031 | bcs 1f @ value is negative | |
4202ce82 | 1032 | cmp r2, #(127 << 24) |
6883a666 NP |
1033 | bcc 1f @ value is too small |
1034 | mov r3, #(127 + 31) | |
1035 | subs r2, r3, r2, lsr #24 | |
1036 | bmi 2f @ value is too large | |
1037 | ||
1038 | @ scale the value | |
1039 | mov r3, r0, lsl #8 | |
1040 | orr r3, r3, #0x80000000 | |
5b3e6663 | 1041 | shift1 lsr, r0, r3, r2 |
6883a666 | 1042 | RET |
4202ce82 | 1043 | |
6883a666 | 1044 | 1: mov r0, #0 |
4202ce82 RE |
1045 | RET |
1046 | ||
6883a666 NP |
1047 | 2: cmp r2, #(127 + 31 - 0xff) |
1048 | bne 3f | |
1049 | movs r2, r0, lsl #9 | |
1050 | bne 4f @ r0 is NAN. | |
1051 | 3: mov r0, #0xffffffff @ maximum unsigned si | |
4202ce82 RE |
1052 | RET |
1053 | ||
6883a666 | 1054 | 4: mov r0, #0 @ What should we convert NAN to? |
496b84c8 RE |
1055 | RET |
1056 | ||
b3f8d95d | 1057 | FUNC_END aeabi_f2uiz |
496b84c8 | 1058 | FUNC_END fixunssfsi |
4202ce82 | 1059 | |
496b84c8 | 1060 | #endif /* L_fixunssfsi */ |