]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgcc/config/m68k/lb1sf68.S
Update copyright years.
[thirdparty/gcc.git] / libgcc / config / m68k / lb1sf68.S
CommitLineData
7857f134 1/* libgcc routines for 68000 w/o floating-point hardware.
5624e564 2 Copyright (C) 1994-2015 Free Software Foundation, Inc.
0d64f74c 3
7ec022b2 4This file is part of GCC.
72832685 5
7ec022b2 6GCC is free software; you can redistribute it and/or modify it
0d64f74c 7under the terms of the GNU General Public License as published by the
748086b7 8Free Software Foundation; either version 3, or (at your option) any
0d64f74c
DE
9later version.
10
0d64f74c
DE
11This file is distributed in the hope that it will be useful, but
12WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14General Public License for more details.
15
748086b7
JJ
16Under Section 7 of GPL version 3, you are granted additional
17permissions described in the GCC Runtime Library Exception, version
183.1, as published by the Free Software Foundation.
0d64f74c 19
748086b7
JJ
20You should have received a copy of the GNU General Public License and
21a copy of the GCC Runtime Library Exception along with this program;
22see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
23<http://www.gnu.org/licenses/>. */
0d64f74c
DE
24
25/* Use this one for any 680x0; assumes no floating point hardware.
26 The trailing " '" appearing on some lines is for ANSI preprocessors. Yuk.
27 Some of this code comes from MINIX, via the folks at ericsson.
28 D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992
29*/
30
31/* These are predefined by new versions of GNU cpp. */
32
33#ifndef __USER_LABEL_PREFIX__
34#define __USER_LABEL_PREFIX__ _
35#endif
36
37#ifndef __REGISTER_PREFIX__
38#define __REGISTER_PREFIX__
39#endif
40
74a35b2b
KR
41#ifndef __IMMEDIATE_PREFIX__
42#define __IMMEDIATE_PREFIX__ #
43#endif
44
0d64f74c
DE
45/* ANSI concatenation macros. */
46
47#define CONCAT1(a, b) CONCAT2(a, b)
48#define CONCAT2(a, b) a ## b
49
50/* Use the right prefix for global labels. */
51
52#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
53
2786eb8d
MM
54/* Note that X is a function. */
55
56#ifdef __ELF__
57#define FUNC(x) .type SYM(x),function
58#else
59/* The .proc pseudo-op is accepted, but ignored, by GAS. We could just
60 define this to the empty string for non-ELF systems, but defining it
61 to .proc means that the information is available to the assembler if
62 the need arises. */
63#define FUNC(x) .proc
64#endif
65
0d64f74c
DE
66/* Use the right prefix for registers. */
67
68#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
69
74a35b2b
KR
70/* Use the right prefix for immediate values. */
71
72#define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x)
73
0d64f74c
DE
74#define d0 REG (d0)
75#define d1 REG (d1)
76#define d2 REG (d2)
77#define d3 REG (d3)
78#define d4 REG (d4)
79#define d5 REG (d5)
80#define d6 REG (d6)
81#define d7 REG (d7)
82#define a0 REG (a0)
83#define a1 REG (a1)
84#define a2 REG (a2)
85#define a3 REG (a3)
86#define a4 REG (a4)
87#define a5 REG (a5)
88#define a6 REG (a6)
89#define fp REG (fp)
90#define sp REG (sp)
a2ef3db7
BI
91#define pc REG (pc)
92
93/* Provide a few macros to allow for PIC code support.
94 * With PIC, data is stored A5 relative so we've got to take a bit of special
95 * care to ensure that all loads of global data is via A5. PIC also requires
96 * jumps and subroutine calls to be PC relative rather than absolute. We cheat
97 * a little on this and in the PIC case, we use short offset branches and
98 * hope that the final object code is within range (which it should be).
99 */
100#ifndef __PIC__
101
102 /* Non PIC (absolute/relocatable) versions */
103
104 .macro PICCALL addr
105 jbsr \addr
106 .endm
107
108 .macro PICJUMP addr
109 jmp \addr
110 .endm
111
112 .macro PICLEA sym, reg
113 lea \sym, \reg
114 .endm
115
116 .macro PICPEA sym, areg
117 pea \sym
118 .endm
119
120#else /* __PIC__ */
121
bd0e50ee
MS
122# if defined (__uClinux__)
123
124 /* Versions for uClinux */
125
126# if defined(__ID_SHARED_LIBRARY__)
a2ef3db7
BI
127
128 /* -mid-shared-library versions */
129
130 .macro PICLEA sym, reg
131 movel a5@(_current_shared_library_a5_offset_), \reg
132 movel \sym@GOT(\reg), \reg
133 .endm
134
135 .macro PICPEA sym, areg
136 movel a5@(_current_shared_library_a5_offset_), \areg
137 movel \sym@GOT(\areg), sp@-
138 .endm
139
c1af059c
NS
140 .macro PICCALL addr
141 PICLEA \addr,a0
142 jsr a0@
143 .endm
144
145 .macro PICJUMP addr
146 PICLEA \addr,a0
147 jmp a0@
148 .endm
149
bd0e50ee 150# else /* !__ID_SHARED_LIBRARY__ */
a2ef3db7
BI
151
152 /* Versions for -msep-data */
153
154 .macro PICLEA sym, reg
155 movel \sym@GOT(a5), \reg
156 .endm
157
158 .macro PICPEA sym, areg
159 movel \sym@GOT(a5), sp@-
160 .endm
161
c1af059c
NS
162 .macro PICCALL addr
163#if defined (__mcoldfire__) && !defined (__mcfisab__) && !defined (__mcfisac__)
164 lea \addr-.-8,a0
165 jsr pc@(a0)
166#else
74d174c6 167 jbsr \addr
c1af059c
NS
168#endif
169 .endm
170
171 .macro PICJUMP addr
172 /* ISA C has no bra.l instruction, and since this assembly file
173 gets assembled into multiple object files, we avoid the
174 bra instruction entirely. */
175#if defined (__mcoldfire__) && !defined (__mcfisab__)
176 lea \addr-.-8,a0
177 jmp pc@(a0)
178#else
179 bra \addr
180#endif
181 .endm
182
bd0e50ee
MS
183# endif
184
185# else /* !__uClinux__ */
186
187 /* Versions for Linux */
188
189 .macro PICLEA sym, reg
190 movel #_GLOBAL_OFFSET_TABLE_@GOTPC, \reg
191 lea (-6, pc, \reg), \reg
192 movel \sym@GOT(\reg), \reg
193 .endm
194
195 .macro PICPEA sym, areg
196 movel #_GLOBAL_OFFSET_TABLE_@GOTPC, \areg
197 lea (-6, pc, \areg), \areg
198 movel \sym@GOT(\areg), sp@-
199 .endm
200
c1af059c
NS
201 .macro PICCALL addr
202#if defined (__mcoldfire__) && !defined (__mcfisab__) && !defined (__mcfisac__)
203 lea \addr-.-8,a0
204 jsr pc@(a0)
205#else
74d174c6 206 jbsr \addr
c1af059c
NS
207#endif
208 .endm
209
210 .macro PICJUMP addr
211 /* ISA C has no bra.l instruction, and since this assembly file
212 gets assembled into multiple object files, we avoid the
213 bra instruction entirely. */
214#if defined (__mcoldfire__) && !defined (__mcfisab__)
215 lea \addr-.-8,a0
216 jmp pc@(a0)
217#else
218 bra \addr
219#endif
220 .endm
221
bd0e50ee 222# endif
a2ef3db7
BI
223#endif /* __PIC__ */
224
0d64f74c
DE
225
226#ifdef L_floatex
227
228| This is an attempt at a decent floating point (single, double and
229| extended double) code for the GNU C compiler. It should be easy to
230| adapt to other compilers (but beware of the local labels!).
231
232| Starting date: 21 October, 1990
233
234| It is convenient to introduce the notation (s,e,f) for a floating point
235| number, where s=sign, e=exponent, f=fraction. We will call a floating
236| point number fpn to abbreviate, independently of the precision.
237| Let MAX_EXP be in each case the maximum exponent (255 for floats, 1023
238| for doubles and 16383 for long doubles). We then have the following
239| different cases:
240| 1. Normalized fpns have 0 < e < MAX_EXP. They correspond to
241| (-1)^s x 1.f x 2^(e-bias-1).
242| 2. Denormalized fpns have e=0. They correspond to numbers of the form
243| (-1)^s x 0.f x 2^(-bias).
244| 3. +/-INFINITY have e=MAX_EXP, f=0.
245| 4. Quiet NaN (Not a Number) have all bits set.
246| 5. Signaling NaN (Not a Number) have s=0, e=MAX_EXP, f=1.
247
248|=============================================================================
249| exceptions
250|=============================================================================
251
252| This is the floating point condition code register (_fpCCR):
253|
254| struct {
255| short _exception_bits;
256| short _trap_enable_bits;
257| short _sticky_bits;
258| short _rounding_mode;
259| short _format;
260| short _last_operation;
261| union {
262| float sf;
263| double df;
264| } _operand1;
265| union {
266| float sf;
267| double df;
268| } _operand2;
269| } _fpCCR;
270
271 .data
272 .even
273
274 .globl SYM (_fpCCR)
275
276SYM (_fpCCR):
277__exception_bits:
278 .word 0
279__trap_enable_bits:
280 .word 0
281__sticky_bits:
282 .word 0
283__rounding_mode:
284 .word ROUND_TO_NEAREST
285__format:
286 .word NIL
287__last_operation:
288 .word NOOP
289__operand1:
290 .long 0
291 .long 0
292__operand2:
293 .long 0
294 .long 0
295
296| Offsets:
297EBITS = __exception_bits - SYM (_fpCCR)
298TRAPE = __trap_enable_bits - SYM (_fpCCR)
299STICK = __sticky_bits - SYM (_fpCCR)
300ROUND = __rounding_mode - SYM (_fpCCR)
301FORMT = __format - SYM (_fpCCR)
302LASTO = __last_operation - SYM (_fpCCR)
303OPER1 = __operand1 - SYM (_fpCCR)
304OPER2 = __operand2 - SYM (_fpCCR)
305
306| The following exception types are supported:
307INEXACT_RESULT = 0x0001
308UNDERFLOW = 0x0002
309OVERFLOW = 0x0004
310DIVIDE_BY_ZERO = 0x0008
311INVALID_OPERATION = 0x0010
312
313| The allowed rounding modes are:
314UNKNOWN = -1
315ROUND_TO_NEAREST = 0 | round result to nearest representable value
316ROUND_TO_ZERO = 1 | round result towards zero
317ROUND_TO_PLUS = 2 | round result towards plus infinity
318ROUND_TO_MINUS = 3 | round result towards minus infinity
319
320| The allowed values of format are:
321NIL = 0
322SINGLE_FLOAT = 1
323DOUBLE_FLOAT = 2
324LONG_FLOAT = 3
325
326| The allowed values for the last operation are:
327NOOP = 0
328ADD = 1
329MULTIPLY = 2
330DIVIDE = 3
331NEGATE = 4
332COMPARE = 5
333EXTENDSFDF = 6
334TRUNCDFSF = 7
335
336|=============================================================================
337| __clear_sticky_bits
338|=============================================================================
339
340| The sticky bits are normally not cleared (thus the name), whereas the
341| exception type and exception value reflect the last computation.
342| This routine is provided to clear them (you can also write to _fpCCR,
343| since it is globally visible).
344
345 .globl SYM (__clear_sticky_bit)
346
347 .text
348 .even
349
350| void __clear_sticky_bits(void);
351SYM (__clear_sticky_bit):
a2ef3db7 352 PICLEA SYM (_fpCCR),a0
9425fb04 353#ifndef __mcoldfire__
74a35b2b 354 movew IMM (0),a0@(STICK)
e82673c4
RK
355#else
356 clr.w a0@(STICK)
357#endif
0d64f74c
DE
358 rts
359
360|=============================================================================
361| $_exception_handler
362|=============================================================================
363
364 .globl $_exception_handler
365
366 .text
367 .even
368
369| This is the common exit point if an exception occurs.
370| NOTE: it is NOT callable from C!
371| It expects the exception type in d7, the format (SINGLE_FLOAT,
372| DOUBLE_FLOAT or LONG_FLOAT) in d6, and the last operation code in d5.
373| It sets the corresponding exception and sticky bits, and the format.
374| Depending on the format if fills the corresponding slots for the
375| operands which produced the exception (all this information is provided
376| so if you write your own exception handlers you have enough information
377| to deal with the problem).
378| Then checks to see if the corresponding exception is trap-enabled,
379| in which case it pushes the address of _fpCCR and traps through
380| trap FPTRAP (15 for the moment).
381
382FPTRAP = 15
383
384$_exception_handler:
a2ef3db7 385 PICLEA SYM (_fpCCR),a0
0d64f74c 386 movew d7,a0@(EBITS) | set __exception_bits
9425fb04 387#ifndef __mcoldfire__
0d64f74c 388 orw d7,a0@(STICK) | and __sticky_bits
686cada4
ILT
389#else
390 movew a0@(STICK),d4
391 orl d7,d4
392 movew d4,a0@(STICK)
393#endif
0d64f74c
DE
394 movew d6,a0@(FORMT) | and __format
395 movew d5,a0@(LASTO) | and __last_operation
396
397| Now put the operands in place:
9425fb04 398#ifndef __mcoldfire__
74a35b2b 399 cmpw IMM (SINGLE_FLOAT),d6
686cada4
ILT
400#else
401 cmpl IMM (SINGLE_FLOAT),d6
402#endif
0d64f74c
DE
403 beq 1f
404 movel a6@(8),a0@(OPER1)
405 movel a6@(12),a0@(OPER1+4)
406 movel a6@(16),a0@(OPER2)
407 movel a6@(20),a0@(OPER2+4)
408 bra 2f
4091: movel a6@(8),a0@(OPER1)
410 movel a6@(12),a0@(OPER2)
4112:
412| And check whether the exception is trap-enabled:
9425fb04 413#ifndef __mcoldfire__
0d64f74c 414 andw a0@(TRAPE),d7 | is exception trap-enabled?
686cada4
ILT
415#else
416 clrl d6
417 movew a0@(TRAPE),d6
418 andl d6,d7
419#endif
0d64f74c 420 beq 1f | no, exit
a2ef3db7 421 PICPEA SYM (_fpCCR),a1 | yes, push address of _fpCCR
74a35b2b 422 trap IMM (FPTRAP) | and trap
9425fb04 423#ifndef __mcoldfire__
0d64f74c 4241: moveml sp@+,d2-d7 | restore data registers
e82673c4
RK
425#else
4261: moveml sp@,d2-d7
427 | XXX if frame pointer is ever removed, stack pointer must
428 | be adjusted here.
429#endif
0d64f74c
DE
430 unlk a6 | and return
431 rts
432#endif /* L_floatex */
433
434#ifdef L_mulsi3
435 .text
2786eb8d 436 FUNC(__mulsi3)
0d64f74c
DE
437 .globl SYM (__mulsi3)
438SYM (__mulsi3):
272627c1
TG
439 movew sp@(4), d0 /* x0 -> d0 */
440 muluw sp@(10), d0 /* x0*y1 */
441 movew sp@(6), d1 /* x1 -> d1 */
442 muluw sp@(8), d1 /* x1*y0 */
9425fb04 443#ifndef __mcoldfire__
0d64f74c 444 addw d1, d0
686cada4
ILT
445#else
446 addl d1, d0
447#endif
272627c1
TG
448 swap d0
449 clrw d0
450 movew sp@(6), d1 /* x1 -> d1 */
451 muluw sp@(10), d1 /* x1*y1 */
0d64f74c 452 addl d1, d0
272627c1 453
0d64f74c 454 rts
0d64f74c
DE
455#endif /* L_mulsi3 */
456
457#ifdef L_udivsi3
458 .text
2786eb8d 459 FUNC(__udivsi3)
0d64f74c
DE
460 .globl SYM (__udivsi3)
461SYM (__udivsi3):
9425fb04 462#ifndef __mcoldfire__
272627c1
TG
463 movel d2, sp@-
464 movel sp@(12), d1 /* d1 = divisor */
465 movel sp@(8), d0 /* d0 = dividend */
466
74a35b2b 467 cmpl IMM (0x10000), d1 /* divisor >= 2 ^ 16 ? */
272627c1
TG
468 jcc L3 /* then try next algorithm */
469 movel d0, d2
470 clrw d2
471 swap d2
472 divu d1, d2 /* high quotient in lower word */
473 movew d2, d0 /* save high quotient */
474 swap d0
475 movew sp@(10), d2 /* get low dividend + high rest */
476 divu d1, d2 /* low quotient */
477 movew d2, d0
478 jra L6
479
480L3: movel d1, d2 /* use d2 as divisor backup */
74a35b2b
KR
481L4: lsrl IMM (1), d1 /* shift divisor */
482 lsrl IMM (1), d0 /* shift dividend */
483 cmpl IMM (0x10000), d1 /* still divisor >= 2 ^ 16 ? */
272627c1 484 jcc L4
c16eadc7 485 divu d1, d0 /* now we have 16-bit divisor */
74a35b2b 486 andl IMM (0xffff), d0 /* mask out divisor, ignore remainder */
272627c1 487
c16eadc7
KH
488/* Multiply the 16-bit tentative quotient with the 32-bit divisor. Because of
489 the operand ranges, this might give a 33-bit product. If this product is
272627c1
TG
490 greater than the dividend, the tentative quotient was too large. */
491 movel d2, d1
492 mulu d0, d1 /* low part, 32 bits */
493 swap d2
494 mulu d0, d2 /* high part, at most 17 bits */
495 swap d2 /* align high part with low part */
f3f69b68 496 tstw d2 /* high part 17 bits? */
272627c1
TG
497 jne L5 /* if 17 bits, quotient was too large */
498 addl d2, d1 /* add parts */
499 jcs L5 /* if sum is 33 bits, quotient was too large */
500 cmpl sp@(8), d1 /* compare the sum with the dividend */
501 jls L6 /* if sum > dividend, quotient was too large */
74a35b2b 502L5: subql IMM (1), d0 /* adjust quotient */
272627c1
TG
503
504L6: movel sp@+, d2
0d64f74c 505 rts
686cada4 506
9425fb04 507#else /* __mcoldfire__ */
686cada4 508
c16eadc7 509/* ColdFire implementation of non-restoring division algorithm from
686cada4 510 Hennessy & Patterson, Appendix A. */
e82673c4
RK
511 link a6,IMM (-12)
512 moveml d2-d4,sp@
686cada4
ILT
513 movel a6@(8),d0
514 movel a6@(12),d1
515 clrl d2 | clear p
516 moveq IMM (31),d4
517L1: addl d0,d0 | shift reg pair (p,a) one bit left
518 addxl d2,d2
519 movl d2,d3 | subtract b from p, store in tmp.
520 subl d1,d3
03db53b1
JW
521 jcs L2 | if no carry,
522 bset IMM (0),d0 | set the low order bit of a to 1,
523 movl d3,d2 | and store tmp in p.
686cada4
ILT
524L2: subql IMM (1),d4
525 jcc L1
9ab8cffd 526 moveml sp@,d2-d4 | restore data registers
686cada4
ILT
527 unlk a6 | and return
528 rts
9425fb04 529#endif /* __mcoldfire__ */
686cada4 530
0d64f74c
DE
531#endif /* L_udivsi3 */
532
0d64f74c
DE
533#ifdef L_divsi3
534 .text
2786eb8d 535 FUNC(__divsi3)
0d64f74c
DE
536 .globl SYM (__divsi3)
537SYM (__divsi3):
272627c1
TG
538 movel d2, sp@-
539
686cada4 540 moveq IMM (1), d2 /* sign of result stored in d2 (=1 or =-1) */
272627c1
TG
541 movel sp@(12), d1 /* d1 = divisor */
542 jpl L1
0d64f74c 543 negl d1
9425fb04 544#ifndef __mcoldfire__
272627c1 545 negb d2 /* change sign because divisor <0 */
686cada4
ILT
546#else
547 negl d2 /* change sign because divisor <0 */
548#endif
272627c1
TG
549L1: movel sp@(8), d0 /* d0 = dividend */
550 jpl L2
551 negl d0
9425fb04 552#ifndef __mcoldfire__
272627c1 553 negb d2
686cada4
ILT
554#else
555 negl d2
556#endif
272627c1
TG
557
558L2: movel d1, sp@-
559 movel d0, sp@-
a2ef3db7 560 PICCALL SYM (__udivsi3) /* divide abs(dividend) by abs(divisor) */
74a35b2b 561 addql IMM (8), sp
0d64f74c 562
272627c1
TG
563 tstb d2
564 jpl L3
0d64f74c
DE
565 negl d0
566
272627c1 567L3: movel sp@+, d2
0d64f74c 568 rts
0d64f74c
DE
569#endif /* L_divsi3 */
570
571#ifdef L_umodsi3
572 .text
2786eb8d 573 FUNC(__umodsi3)
0d64f74c
DE
574 .globl SYM (__umodsi3)
575SYM (__umodsi3):
272627c1
TG
576 movel sp@(8), d1 /* d1 = divisor */
577 movel sp@(4), d0 /* d0 = dividend */
0d64f74c 578 movel d1, sp@-
0d64f74c 579 movel d0, sp@-
a2ef3db7 580 PICCALL SYM (__udivsi3)
74a35b2b 581 addql IMM (8), sp
272627c1 582 movel sp@(8), d1 /* d1 = divisor */
9425fb04 583#ifndef __mcoldfire__
0d64f74c 584 movel d1, sp@-
272627c1 585 movel d0, sp@-
a2ef3db7 586 PICCALL SYM (__mulsi3) /* d0 = (a/b)*b */
74a35b2b 587 addql IMM (8), sp
125bcee0
RK
588#else
589 mulsl d1,d0
590#endif
272627c1
TG
591 movel sp@(4), d1 /* d1 = dividend */
592 subl d0, d1 /* d1 = a - (a/b)*b */
593 movel d1, d0
0d64f74c 594 rts
0d64f74c
DE
595#endif /* L_umodsi3 */
596
597#ifdef L_modsi3
598 .text
2786eb8d 599 FUNC(__modsi3)
0d64f74c
DE
600 .globl SYM (__modsi3)
601SYM (__modsi3):
272627c1
TG
602 movel sp@(8), d1 /* d1 = divisor */
603 movel sp@(4), d0 /* d0 = dividend */
0d64f74c 604 movel d1, sp@-
0d64f74c 605 movel d0, sp@-
a2ef3db7 606 PICCALL SYM (__divsi3)
74a35b2b 607 addql IMM (8), sp
272627c1 608 movel sp@(8), d1 /* d1 = divisor */
9425fb04 609#ifndef __mcoldfire__
0d64f74c 610 movel d1, sp@-
272627c1 611 movel d0, sp@-
a2ef3db7 612 PICCALL SYM (__mulsi3) /* d0 = (a/b)*b */
74a35b2b 613 addql IMM (8), sp
125bcee0
RK
614#else
615 mulsl d1,d0
616#endif
272627c1
TG
617 movel sp@(4), d1 /* d1 = dividend */
618 subl d0, d1 /* d1 = a - (a/b)*b */
619 movel d1, d0
0d64f74c 620 rts
0d64f74c
DE
621#endif /* L_modsi3 */
622
0d64f74c
DE
623
624#ifdef L_double
625
626 .globl SYM (_fpCCR)
627 .globl $_exception_handler
628
629QUIET_NaN = 0xffffffff
630
631D_MAX_EXP = 0x07ff
632D_BIAS = 1022
633DBL_MAX_EXP = D_MAX_EXP - D_BIAS
634DBL_MIN_EXP = 1 - D_BIAS
635DBL_MANT_DIG = 53
636
637INEXACT_RESULT = 0x0001
638UNDERFLOW = 0x0002
639OVERFLOW = 0x0004
640DIVIDE_BY_ZERO = 0x0008
641INVALID_OPERATION = 0x0010
642
643DOUBLE_FLOAT = 2
644
645NOOP = 0
646ADD = 1
647MULTIPLY = 2
648DIVIDE = 3
649NEGATE = 4
650COMPARE = 5
651EXTENDSFDF = 6
652TRUNCDFSF = 7
653
654UNKNOWN = -1
655ROUND_TO_NEAREST = 0 | round result to nearest representable value
656ROUND_TO_ZERO = 1 | round result towards zero
657ROUND_TO_PLUS = 2 | round result towards plus infinity
658ROUND_TO_MINUS = 3 | round result towards minus infinity
659
660| Entry points:
661
662 .globl SYM (__adddf3)
663 .globl SYM (__subdf3)
664 .globl SYM (__muldf3)
665 .globl SYM (__divdf3)
666 .globl SYM (__negdf2)
667 .globl SYM (__cmpdf2)
1a50d5e9 668 .globl SYM (__cmpdf2_internal)
c1af059c 669 .hidden SYM (__cmpdf2_internal)
0d64f74c
DE
670
671 .text
672 .even
673
674| These are common routines to return and signal exceptions.
675
676Ld$den:
677| Return and signal a denormalized number
678 orl d7,d0
8e56feed 679 movew IMM (INEXACT_RESULT+UNDERFLOW),d7
686cada4 680 moveq IMM (DOUBLE_FLOAT),d6
a2ef3db7 681 PICJUMP $_exception_handler
0d64f74c
DE
682
683Ld$infty:
684Ld$overflow:
685| Return a properly signed INFINITY and set the exception flags
74a35b2b
KR
686 movel IMM (0x7ff00000),d0
687 movel IMM (0),d1
0d64f74c 688 orl d7,d0
8e56feed 689 movew IMM (INEXACT_RESULT+OVERFLOW),d7
686cada4 690 moveq IMM (DOUBLE_FLOAT),d6
a2ef3db7 691 PICJUMP $_exception_handler
0d64f74c
DE
692
693Ld$underflow:
694| Return 0 and set the exception flags
74a35b2b 695 movel IMM (0),d0
0d64f74c 696 movel d0,d1
8e56feed 697 movew IMM (INEXACT_RESULT+UNDERFLOW),d7
686cada4 698 moveq IMM (DOUBLE_FLOAT),d6
a2ef3db7 699 PICJUMP $_exception_handler
0d64f74c
DE
700
701Ld$inop:
702| Return a quiet NaN and set the exception flags
74a35b2b 703 movel IMM (QUIET_NaN),d0
0d64f74c 704 movel d0,d1
8e56feed 705 movew IMM (INEXACT_RESULT+INVALID_OPERATION),d7
686cada4 706 moveq IMM (DOUBLE_FLOAT),d6
a2ef3db7 707 PICJUMP $_exception_handler
0d64f74c
DE
708
709Ld$div$0:
710| Return a properly signed INFINITY and set the exception flags
74a35b2b
KR
711 movel IMM (0x7ff00000),d0
712 movel IMM (0),d1
0d64f74c 713 orl d7,d0
8e56feed 714 movew IMM (INEXACT_RESULT+DIVIDE_BY_ZERO),d7
686cada4 715 moveq IMM (DOUBLE_FLOAT),d6
a2ef3db7 716 PICJUMP $_exception_handler
0d64f74c
DE
717
718|=============================================================================
719|=============================================================================
720| double precision routines
721|=============================================================================
722|=============================================================================
723
724| A double precision floating point number (double) has the format:
725|
726| struct _double {
727| unsigned int sign : 1; /* sign bit */
728| unsigned int exponent : 11; /* exponent, shifted by 126 */
729| unsigned int fraction : 52; /* fraction */
730| } double;
731|
732| Thus sizeof(double) = 8 (64 bits).
733|
734| All the routines are callable from C programs, and return the result
735| in the register pair d0-d1. They also preserve all registers except
736| d0-d1 and a0-a1.
737
738|=============================================================================
739| __subdf3
740|=============================================================================
741
742| double __subdf3(double, double);
2786eb8d 743 FUNC(__subdf3)
0d64f74c 744SYM (__subdf3):
74a35b2b 745 bchg IMM (31),sp@(12) | change sign of second operand
0d64f74c
DE
746 | and fall through, so we always add
747|=============================================================================
748| __adddf3
749|=============================================================================
750
751| double __adddf3(double, double);
2786eb8d 752 FUNC(__adddf3)
0d64f74c 753SYM (__adddf3):
9425fb04 754#ifndef __mcoldfire__
74a35b2b 755 link a6,IMM (0) | everything will be done in registers
0d64f74c 756 moveml d2-d7,sp@- | save all data registers and a2 (but d0-d1)
e82673c4
RK
757#else
758 link a6,IMM (-24)
759 moveml d2-d7,sp@
760#endif
0d64f74c
DE
761 movel a6@(8),d0 | get first operand
762 movel a6@(12),d1 |
763 movel a6@(16),d2 | get second operand
764 movel a6@(20),d3 |
765
766 movel d0,d7 | get d0's sign bit in d7 '
767 addl d1,d1 | check and clear sign bit of a, and gain one
768 addxl d0,d0 | bit of extra precision
769 beq Ladddf$b | if zero return second operand
770
771 movel d2,d6 | save sign in d6
772 addl d3,d3 | get rid of sign bit and gain one bit of
773 addxl d2,d2 | extra precision
774 beq Ladddf$a | if zero return first operand
775
74a35b2b 776 andl IMM (0x80000000),d7 | isolate a's sign bit '
0d64f74c 777 swap d6 | and also b's sign bit '
9425fb04 778#ifndef __mcoldfire__
74a35b2b 779 andw IMM (0x8000),d6 |
0d64f74c
DE
780 orw d6,d7 | and combine them into d7, so that a's sign '
781 | bit is in the high word and b's is in the '
782 | low word, so d6 is free to be used
686cada4
ILT
783#else
784 andl IMM (0x8000),d6
785 orl d6,d7
786#endif
0d64f74c
DE
787 movel d7,a0 | now save d7 into a0, so d7 is free to
788 | be used also
789
790| Get the exponents and check for denormalized and/or infinity.
791
74a35b2b
KR
792 movel IMM (0x001fffff),d6 | mask for the fraction
793 movel IMM (0x00200000),d7 | mask to put hidden bit back
0d64f74c
DE
794
795 movel d0,d4 |
796 andl d6,d0 | get fraction in d0
797 notl d6 | make d6 into mask for the exponent
798 andl d6,d4 | get exponent in d4
799 beq Ladddf$a$den | branch if a is denormalized
800 cmpl d6,d4 | check for INFINITY or NaN
801 beq Ladddf$nf |
802 orl d7,d0 | and put hidden bit back
803Ladddf$1:
804 swap d4 | shift right exponent so that it starts
9425fb04 805#ifndef __mcoldfire__
74a35b2b 806 lsrw IMM (5),d4 | in bit 0 and not bit 20
686cada4
ILT
807#else
808 lsrl IMM (5),d4 | in bit 0 and not bit 20
809#endif
0d64f74c
DE
810| Now we have a's exponent in d4 and fraction in d0-d1 '
811 movel d2,d5 | save b to get exponent
812 andl d6,d5 | get exponent in d5
813 beq Ladddf$b$den | branch if b is denormalized
814 cmpl d6,d5 | check for INFINITY or NaN
815 beq Ladddf$nf
816 notl d6 | make d6 into mask for the fraction again
817 andl d6,d2 | and get fraction in d2
818 orl d7,d2 | and put hidden bit back
819Ladddf$2:
820 swap d5 | shift right exponent so that it starts
9425fb04 821#ifndef __mcoldfire__
74a35b2b 822 lsrw IMM (5),d5 | in bit 0 and not bit 20
686cada4
ILT
823#else
824 lsrl IMM (5),d5 | in bit 0 and not bit 20
825#endif
0d64f74c
DE
826
827| Now we have b's exponent in d5 and fraction in d2-d3. '
828
829| The situation now is as follows: the signs are combined in a0, the
830| numbers are in d0-d1 (a) and d2-d3 (b), and the exponents in d4 (a)
831| and d5 (b). To do the rounding correctly we need to keep all the
832| bits until the end, so we need to use d0-d1-d2-d3 for the first number
833| and d4-d5-d6-d7 for the second. To do this we store (temporarily) the
834| exponents in a2-a3.
835
9425fb04 836#ifndef __mcoldfire__
0d64f74c 837 moveml a2-a3,sp@- | save the address registers
686cada4 838#else
e82673c4
RK
839 movel a2,sp@-
840 movel a3,sp@-
841 movel a4,sp@-
686cada4 842#endif
0d64f74c
DE
843
844 movel d4,a2 | save the exponents
845 movel d5,a3 |
846
74a35b2b 847 movel IMM (0),d7 | and move the numbers around
0d64f74c
DE
848 movel d7,d6 |
849 movel d3,d5 |
850 movel d2,d4 |
851 movel d7,d3 |
852 movel d7,d2 |
853
854| Here we shift the numbers until the exponents are the same, and put
855| the largest exponent in a2.
9425fb04 856#ifndef __mcoldfire__
0d64f74c
DE
857 exg d4,a2 | get exponents back
858 exg d5,a3 |
859 cmpw d4,d5 | compare the exponents
686cada4
ILT
860#else
861 movel d4,a4 | get exponents back
862 movel a2,d4
863 movel a4,a2
864 movel d5,a4
865 movel a3,d5
866 movel a4,a3
867 cmpl d4,d5 | compare the exponents
868#endif
0d64f74c
DE
869 beq Ladddf$3 | if equal don't shift '
870 bhi 9f | branch if second exponent is higher
871
872| Here we have a's exponent larger than b's, so we have to shift b. We do
873| this by using as counter d2:
8741: movew d4,d2 | move largest exponent to d2
9425fb04 875#ifndef __mcoldfire__
ddd5a7c1 876 subw d5,d2 | and subtract second exponent
0d64f74c
DE
877 exg d4,a2 | get back the longs we saved
878 exg d5,a3 |
686cada4
ILT
879#else
880 subl d5,d2 | and subtract second exponent
881 movel d4,a4 | get back the longs we saved
882 movel a2,d4
883 movel a4,a2
884 movel d5,a4
885 movel a3,d5
886 movel a4,a3
887#endif
0d64f74c 888| if difference is too large we don't shift (actually, we can just exit) '
9425fb04 889#ifndef __mcoldfire__
74a35b2b 890 cmpw IMM (DBL_MANT_DIG+2),d2
686cada4
ILT
891#else
892 cmpl IMM (DBL_MANT_DIG+2),d2
893#endif
0d64f74c 894 bge Ladddf$b$small
9425fb04 895#ifndef __mcoldfire__
74a35b2b 896 cmpw IMM (32),d2 | if difference >= 32, shift by longs
686cada4
ILT
897#else
898 cmpl IMM (32),d2 | if difference >= 32, shift by longs
899#endif
0d64f74c 900 bge 5f
686cada4 9012:
9425fb04 902#ifndef __mcoldfire__
686cada4
ILT
903 cmpw IMM (16),d2 | if difference >= 16, shift by words
904#else
905 cmpl IMM (16),d2 | if difference >= 16, shift by words
906#endif
0d64f74c
DE
907 bge 6f
908 bra 3f | enter dbra loop
909
686cada4 9104:
9425fb04 911#ifndef __mcoldfire__
686cada4 912 lsrl IMM (1),d4
74a35b2b
KR
913 roxrl IMM (1),d5
914 roxrl IMM (1),d6
915 roxrl IMM (1),d7
686cada4
ILT
916#else
917 lsrl IMM (1),d7
918 btst IMM (0),d6
919 beq 10f
920 bset IMM (31),d7
92110: lsrl IMM (1),d6
922 btst IMM (0),d5
923 beq 11f
924 bset IMM (31),d6
92511: lsrl IMM (1),d5
926 btst IMM (0),d4
927 beq 12f
928 bset IMM (31),d5
92912: lsrl IMM (1),d4
930#endif
9313:
9425fb04 932#ifndef __mcoldfire__
686cada4
ILT
933 dbra d2,4b
934#else
935 subql IMM (1),d2
936 bpl 4b
937#endif
74a35b2b 938 movel IMM (0),d2
0d64f74c
DE
939 movel d2,d3
940 bra Ladddf$4
9415:
942 movel d6,d7
943 movel d5,d6
944 movel d4,d5
74a35b2b 945 movel IMM (0),d4
9425fb04 946#ifndef __mcoldfire__
74a35b2b 947 subw IMM (32),d2
686cada4
ILT
948#else
949 subl IMM (32),d2
950#endif
0d64f74c
DE
951 bra 2b
9526:
953 movew d6,d7
954 swap d7
955 movew d5,d6
956 swap d6
957 movew d4,d5
958 swap d5
74a35b2b 959 movew IMM (0),d4
0d64f74c 960 swap d4
9425fb04 961#ifndef __mcoldfire__
74a35b2b 962 subw IMM (16),d2
686cada4
ILT
963#else
964 subl IMM (16),d2
965#endif
0d64f74c
DE
966 bra 3b
967
686cada4 9689:
9425fb04 969#ifndef __mcoldfire__
686cada4 970 exg d4,d5
0d64f74c
DE
971 movew d4,d6
972 subw d5,d6 | keep d5 (largest exponent) in d4
973 exg d4,a2
974 exg d5,a3
686cada4
ILT
975#else
976 movel d5,d6
977 movel d4,d5
978 movel d6,d4
979 subl d5,d6
980 movel d4,a4
981 movel a2,d4
982 movel a4,a2
983 movel d5,a4
984 movel a3,d5
985 movel a4,a3
986#endif
0d64f74c 987| if difference is too large we don't shift (actually, we can just exit) '
9425fb04 988#ifndef __mcoldfire__
74a35b2b 989 cmpw IMM (DBL_MANT_DIG+2),d6
686cada4
ILT
990#else
991 cmpl IMM (DBL_MANT_DIG+2),d6
992#endif
0d64f74c 993 bge Ladddf$a$small
9425fb04 994#ifndef __mcoldfire__
74a35b2b 995 cmpw IMM (32),d6 | if difference >= 32, shift by longs
686cada4
ILT
996#else
997 cmpl IMM (32),d6 | if difference >= 32, shift by longs
998#endif
0d64f74c 999 bge 5f
686cada4 10002:
9425fb04 1001#ifndef __mcoldfire__
686cada4
ILT
1002 cmpw IMM (16),d6 | if difference >= 16, shift by words
1003#else
1004 cmpl IMM (16),d6 | if difference >= 16, shift by words
1005#endif
0d64f74c
DE
1006 bge 6f
1007 bra 3f | enter dbra loop
1008
686cada4 10094:
9425fb04 1010#ifndef __mcoldfire__
686cada4 1011 lsrl IMM (1),d0
74a35b2b
KR
1012 roxrl IMM (1),d1
1013 roxrl IMM (1),d2
1014 roxrl IMM (1),d3
686cada4
ILT
1015#else
1016 lsrl IMM (1),d3
1017 btst IMM (0),d2
1018 beq 10f
1019 bset IMM (31),d3
102010: lsrl IMM (1),d2
1021 btst IMM (0),d1
1022 beq 11f
1023 bset IMM (31),d2
102411: lsrl IMM (1),d1
1025 btst IMM (0),d0
1026 beq 12f
1027 bset IMM (31),d1
102812: lsrl IMM (1),d0
1029#endif
10303:
9425fb04 1031#ifndef __mcoldfire__
686cada4
ILT
1032 dbra d6,4b
1033#else
1034 subql IMM (1),d6
1035 bpl 4b
1036#endif
74a35b2b 1037 movel IMM (0),d7
0d64f74c
DE
1038 movel d7,d6
1039 bra Ladddf$4
10405:
1041 movel d2,d3
1042 movel d1,d2
1043 movel d0,d1
74a35b2b 1044 movel IMM (0),d0
9425fb04 1045#ifndef __mcoldfire__
74a35b2b 1046 subw IMM (32),d6
686cada4
ILT
1047#else
1048 subl IMM (32),d6
1049#endif
0d64f74c
DE
1050 bra 2b
10516:
1052 movew d2,d3
1053 swap d3
1054 movew d1,d2
1055 swap d2
1056 movew d0,d1
1057 swap d1
74a35b2b 1058 movew IMM (0),d0
0d64f74c 1059 swap d0
9425fb04 1060#ifndef __mcoldfire__
74a35b2b 1061 subw IMM (16),d6
686cada4
ILT
1062#else
1063 subl IMM (16),d6
1064#endif
0d64f74c
DE
1065 bra 3b
1066Ladddf$3:
9425fb04 1067#ifndef __mcoldfire__
0d64f74c
DE
1068 exg d4,a2
1069 exg d5,a3
686cada4
ILT
1070#else
1071 movel d4,a4
1072 movel a2,d4
1073 movel a4,a2
1074 movel d5,a4
1075 movel a3,d5
1076 movel a4,a3
1077#endif
0d64f74c
DE
1078Ladddf$4:
1079| Now we have the numbers in d0--d3 and d4--d7, the exponent in a2, and
1080| the signs in a4.
1081
ddd5a7c1 1082| Here we have to decide whether to add or subtract the numbers:
9425fb04 1083#ifndef __mcoldfire__
0d64f74c
DE
1084 exg d7,a0 | get the signs
1085 exg d6,a3 | a3 is free to be used
686cada4
ILT
1086#else
1087 movel d7,a4
1088 movel a0,d7
1089 movel a4,a0
1090 movel d6,a4
1091 movel a3,d6
1092 movel a4,a3
1093#endif
0d64f74c 1094 movel d7,d6 |
74a35b2b 1095 movew IMM (0),d7 | get a's sign in d7 '
0d64f74c 1096 swap d6 |
74a35b2b 1097 movew IMM (0),d6 | and b's sign in d6 '
0d64f74c
DE
1098 eorl d7,d6 | compare the signs
1099 bmi Lsubdf$0 | if the signs are different we have
ddd5a7c1 1100 | to subtract
9425fb04 1101#ifndef __mcoldfire__
0d64f74c
DE
1102 exg d7,a0 | else we add the numbers
1103 exg d6,a3 |
686cada4
ILT
1104#else
1105 movel d7,a4
1106 movel a0,d7
1107 movel a4,a0
1108 movel d6,a4
1109 movel a3,d6
1110 movel a4,a3
1111#endif
0d64f74c
DE
1112 addl d7,d3 |
1113 addxl d6,d2 |
1114 addxl d5,d1 |
1115 addxl d4,d0 |
1116
1117 movel a2,d4 | return exponent to d4
1118 movel a0,d7 |
74a35b2b 1119 andl IMM (0x80000000),d7 | d7 now has the sign
0d64f74c 1120
9425fb04 1121#ifndef __mcoldfire__
0d64f74c 1122 moveml sp@+,a2-a3
686cada4 1123#else
e82673c4
RK
1124 movel sp@+,a4
1125 movel sp@+,a3
1126 movel sp@+,a2
686cada4 1127#endif
0d64f74c
DE
1128
1129| Before rounding normalize so bit #DBL_MANT_DIG is set (we will consider
1130| the case of denormalized numbers in the rounding routine itself).
ddd5a7c1 1131| As in the addition (not in the subtraction!) we could have set
0d64f74c 1132| one more bit we check this:
74a35b2b 1133 btst IMM (DBL_MANT_DIG+1),d0
0d64f74c 1134 beq 1f
9425fb04 1135#ifndef __mcoldfire__
74a35b2b
KR
1136 lsrl IMM (1),d0
1137 roxrl IMM (1),d1
1138 roxrl IMM (1),d2
1139 roxrl IMM (1),d3
1140 addw IMM (1),d4
686cada4
ILT
1141#else
1142 lsrl IMM (1),d3
1143 btst IMM (0),d2
1144 beq 10f
1145 bset IMM (31),d3
114610: lsrl IMM (1),d2
1147 btst IMM (0),d1
1148 beq 11f
1149 bset IMM (31),d2
115011: lsrl IMM (1),d1
1151 btst IMM (0),d0
1152 beq 12f
1153 bset IMM (31),d1
115412: lsrl IMM (1),d0
1155 addl IMM (1),d4
1156#endif
0d64f74c 11571:
a2ef3db7
BI
1158 lea pc@(Ladddf$5),a0 | to return from rounding routine
1159 PICLEA SYM (_fpCCR),a1 | check the rounding mode
9425fb04 1160#ifdef __mcoldfire__
686cada4
ILT
1161 clrl d6
1162#endif
0d64f74c
DE
1163 movew a1@(6),d6 | rounding mode in d6
1164 beq Lround$to$nearest
9425fb04 1165#ifndef __mcoldfire__
74a35b2b 1166 cmpw IMM (ROUND_TO_PLUS),d6
686cada4
ILT
1167#else
1168 cmpl IMM (ROUND_TO_PLUS),d6
1169#endif
0d64f74c
DE
1170 bhi Lround$to$minus
1171 blt Lround$to$zero
1172 bra Lround$to$plus
1173Ladddf$5:
1174| Put back the exponent and check for overflow
9425fb04 1175#ifndef __mcoldfire__
74a35b2b 1176 cmpw IMM (0x7ff),d4 | is the exponent big?
686cada4
ILT
1177#else
1178 cmpl IMM (0x7ff),d4 | is the exponent big?
1179#endif
0d64f74c 1180 bge 1f
74a35b2b 1181 bclr IMM (DBL_MANT_DIG-1),d0
9425fb04 1182#ifndef __mcoldfire__
74a35b2b 1183 lslw IMM (4),d4 | put exponent back into position
686cada4
ILT
1184#else
1185 lsll IMM (4),d4 | put exponent back into position
1186#endif
0d64f74c 1187 swap d0 |
9425fb04 1188#ifndef __mcoldfire__
0d64f74c 1189 orw d4,d0 |
686cada4
ILT
1190#else
1191 orl d4,d0 |
1192#endif
0d64f74c
DE
1193 swap d0 |
1194 bra Ladddf$ret
11951:
aa2192f8 1196 moveq IMM (ADD),d5
0d64f74c
DE
1197 bra Ld$overflow
1198
1199Lsubdf$0:
ddd5a7c1 1200| Here we do the subtraction.
9425fb04 1201#ifndef __mcoldfire__
0d64f74c
DE
1202 exg d7,a0 | put sign back in a0
1203 exg d6,a3 |
686cada4
ILT
1204#else
1205 movel d7,a4
1206 movel a0,d7
1207 movel a4,a0
1208 movel d6,a4
1209 movel a3,d6
1210 movel a4,a3
1211#endif
0d64f74c
DE
1212 subl d7,d3 |
1213 subxl d6,d2 |
1214 subxl d5,d1 |
1215 subxl d4,d0 |
1216 beq Ladddf$ret$1 | if zero just exit
1217 bpl 1f | if positive skip the following
686cada4 1218 movel a0,d7 |
74a35b2b 1219 bchg IMM (31),d7 | change sign bit in d7
686cada4 1220 movel d7,a0 |
0d64f74c
DE
1221 negl d3 |
1222 negxl d2 |
1223 negxl d1 | and negate result
1224 negxl d0 |
12251:
1226 movel a2,d4 | return exponent to d4
1227 movel a0,d7
74a35b2b 1228 andl IMM (0x80000000),d7 | isolate sign bit
9425fb04 1229#ifndef __mcoldfire__
0d64f74c 1230 moveml sp@+,a2-a3 |
686cada4 1231#else
e82673c4
RK
1232 movel sp@+,a4
1233 movel sp@+,a3
1234 movel sp@+,a2
686cada4 1235#endif
0d64f74c
DE
1236
1237| Before rounding normalize so bit #DBL_MANT_DIG is set (we will consider
1238| the case of denormalized numbers in the rounding routine itself).
ddd5a7c1 1239| As in the addition (not in the subtraction!) we could have set
0d64f74c 1240| one more bit we check this:
74a35b2b 1241 btst IMM (DBL_MANT_DIG+1),d0
0d64f74c 1242 beq 1f
9425fb04 1243#ifndef __mcoldfire__
74a35b2b
KR
1244 lsrl IMM (1),d0
1245 roxrl IMM (1),d1
1246 roxrl IMM (1),d2
1247 roxrl IMM (1),d3
1248 addw IMM (1),d4
686cada4
ILT
1249#else
1250 lsrl IMM (1),d3
1251 btst IMM (0),d2
1252 beq 10f
1253 bset IMM (31),d3
125410: lsrl IMM (1),d2
1255 btst IMM (0),d1
1256 beq 11f
1257 bset IMM (31),d2
125811: lsrl IMM (1),d1
1259 btst IMM (0),d0
1260 beq 12f
1261 bset IMM (31),d1
126212: lsrl IMM (1),d0
1263 addl IMM (1),d4
1264#endif
0d64f74c 12651:
a2ef3db7
BI
1266 lea pc@(Lsubdf$1),a0 | to return from rounding routine
1267 PICLEA SYM (_fpCCR),a1 | check the rounding mode
9425fb04 1268#ifdef __mcoldfire__
686cada4
ILT
1269 clrl d6
1270#endif
0d64f74c
DE
1271 movew a1@(6),d6 | rounding mode in d6
1272 beq Lround$to$nearest
9425fb04 1273#ifndef __mcoldfire__
74a35b2b 1274 cmpw IMM (ROUND_TO_PLUS),d6
686cada4
ILT
1275#else
1276 cmpl IMM (ROUND_TO_PLUS),d6
1277#endif
0d64f74c
DE
1278 bhi Lround$to$minus
1279 blt Lround$to$zero
1280 bra Lround$to$plus
1281Lsubdf$1:
1282| Put back the exponent and sign (we don't have overflow). '
74a35b2b 1283 bclr IMM (DBL_MANT_DIG-1),d0
9425fb04 1284#ifndef __mcoldfire__
74a35b2b 1285 lslw IMM (4),d4 | put exponent back into position
686cada4
ILT
1286#else
1287 lsll IMM (4),d4 | put exponent back into position
1288#endif
0d64f74c 1289 swap d0 |
9425fb04 1290#ifndef __mcoldfire__
0d64f74c 1291 orw d4,d0 |
686cada4
ILT
1292#else
1293 orl d4,d0 |
1294#endif
0d64f74c
DE
1295 swap d0 |
1296 bra Ladddf$ret
1297
1298| If one of the numbers was too small (difference of exponents >=
1299| DBL_MANT_DIG+1) we return the other (and now we don't have to '
1300| check for finiteness or zero).
1301Ladddf$a$small:
9425fb04 1302#ifndef __mcoldfire__
0d64f74c 1303 moveml sp@+,a2-a3
686cada4 1304#else
e82673c4
RK
1305 movel sp@+,a4
1306 movel sp@+,a3
1307 movel sp@+,a2
686cada4 1308#endif
0d64f74c
DE
1309 movel a6@(16),d0
1310 movel a6@(20),d1
a2ef3db7 1311 PICLEA SYM (_fpCCR),a0
74a35b2b 1312 movew IMM (0),a0@
9425fb04 1313#ifndef __mcoldfire__
0d64f74c 1314 moveml sp@+,d2-d7 | restore data registers
e82673c4
RK
1315#else
1316 moveml sp@,d2-d7
1317 | XXX if frame pointer is ever removed, stack pointer must
1318 | be adjusted here.
1319#endif
0d64f74c
DE
1320 unlk a6 | and return
1321 rts
1322
1323Ladddf$b$small:
9425fb04 1324#ifndef __mcoldfire__
0d64f74c 1325 moveml sp@+,a2-a3
686cada4 1326#else
e82673c4
RK
1327 movel sp@+,a4
1328 movel sp@+,a3
1329 movel sp@+,a2
686cada4 1330#endif
0d64f74c
DE
1331 movel a6@(8),d0
1332 movel a6@(12),d1
a2ef3db7 1333 PICLEA SYM (_fpCCR),a0
74a35b2b 1334 movew IMM (0),a0@
9425fb04 1335#ifndef __mcoldfire__
0d64f74c 1336 moveml sp@+,d2-d7 | restore data registers
e82673c4
RK
1337#else
1338 moveml sp@,d2-d7
1339 | XXX if frame pointer is ever removed, stack pointer must
1340 | be adjusted here.
1341#endif
0d64f74c
DE
1342 unlk a6 | and return
1343 rts
1344
1345Ladddf$a$den:
1346 movel d7,d4 | d7 contains 0x00200000
1347 bra Ladddf$1
1348
1349Ladddf$b$den:
1350 movel d7,d5 | d7 contains 0x00200000
1351 notl d6
1352 bra Ladddf$2
1353
1354Ladddf$b:
1355| Return b (if a is zero)
1356 movel d2,d0
1357 movel d3,d1
75a75b88
PB
1358 bne 1f | Check if b is -0
1359 cmpl IMM (0x80000000),d0
1360 bne 1f
1361 andl IMM (0x80000000),d7 | Use the sign of a
1362 clrl d0
1363 bra Ladddf$ret
0d64f74c
DE
1364Ladddf$a:
1365 movel a6@(8),d0
1366 movel a6@(12),d1
13671:
aa2192f8 1368 moveq IMM (ADD),d5
0d64f74c 1369| Check for NaN and +/-INFINITY.
74a35b2b
KR
1370 movel d0,d7 |
1371 andl IMM (0x80000000),d7 |
1372 bclr IMM (31),d0 |
1373 cmpl IMM (0x7ff00000),d0 |
1374 bge 2f |
1375 movel d0,d0 | check for zero, since we don't '
1376 bne Ladddf$ret | want to return -0 by mistake
1377 bclr IMM (31),d7 |
1378 bra Ladddf$ret |
0d64f74c 13792:
74a35b2b
KR
1380 andl IMM (0x000fffff),d0 | check for NaN (nonzero fraction)
1381 orl d1,d0 |
1382 bne Ld$inop |
1383 bra Ld$infty |
0d64f74c
DE
1384
1385Ladddf$ret$1:
9425fb04 1386#ifndef __mcoldfire__
0d64f74c 1387 moveml sp@+,a2-a3 | restore regs and exit
e82673c4
RK
1388#else
1389 movel sp@+,a4
1390 movel sp@+,a3
1391 movel sp@+,a2
1392#endif
0d64f74c
DE
1393
1394Ladddf$ret:
1395| Normal exit.
a2ef3db7 1396 PICLEA SYM (_fpCCR),a0
74a35b2b 1397 movew IMM (0),a0@
0d64f74c 1398 orl d7,d0 | put sign bit back
9425fb04 1399#ifndef __mcoldfire__
0d64f74c 1400 moveml sp@+,d2-d7
e82673c4
RK
1401#else
1402 moveml sp@,d2-d7
1403 | XXX if frame pointer is ever removed, stack pointer must
1404 | be adjusted here.
1405#endif
0d64f74c
DE
1406 unlk a6
1407 rts
1408
1409Ladddf$ret$den:
1410| Return a denormalized number.
9425fb04 1411#ifndef __mcoldfire__
74a35b2b
KR
1412 lsrl IMM (1),d0 | shift right once more
1413 roxrl IMM (1),d1 |
686cada4
ILT
1414#else
1415 lsrl IMM (1),d1
1416 btst IMM (0),d0
1417 beq 10f
1418 bset IMM (31),d1
141910: lsrl IMM (1),d0
1420#endif
0d64f74c
DE
1421 bra Ladddf$ret
1422
1423Ladddf$nf:
aa2192f8 1424 moveq IMM (ADD),d5
0d64f74c
DE
1425| This could be faster but it is not worth the effort, since it is not
1426| executed very often. We sacrifice speed for clarity here.
1427 movel a6@(8),d0 | get the numbers back (remember that we
1428 movel a6@(12),d1 | did some processing already)
1429 movel a6@(16),d2 |
1430 movel a6@(20),d3 |
74a35b2b 1431 movel IMM (0x7ff00000),d4 | useful constant (INFINITY)
0d64f74c
DE
1432 movel d0,d7 | save sign bits
1433 movel d2,d6 |
74a35b2b
KR
1434 bclr IMM (31),d0 | clear sign bits
1435 bclr IMM (31),d2 |
0d64f74c
DE
1436| We know that one of them is either NaN of +/-INFINITY
1437| Check for NaN (if either one is NaN return NaN)
1438 cmpl d4,d0 | check first a (d0)
1439 bhi Ld$inop | if d0 > 0x7ff00000 or equal and
1440 bne 2f
1441 tstl d1 | d1 > 0, a is NaN
1442 bne Ld$inop |
14432: cmpl d4,d2 | check now b (d1)
1444 bhi Ld$inop |
1445 bne 3f
1446 tstl d3 |
1447 bne Ld$inop |
14483:
1449| Now comes the check for +/-INFINITY. We know that both are (maybe not
1450| finite) numbers, but we have to check if both are infinite whether we
ddd5a7c1 1451| are adding or subtracting them.
0d64f74c
DE
1452 eorl d7,d6 | to check sign bits
1453 bmi 1f
74a35b2b 1454 andl IMM (0x80000000),d7 | get (common) sign bit
0d64f74c
DE
1455 bra Ld$infty
14561:
1457| We know one (or both) are infinite, so we test for equality between the
1458| two numbers (if they are equal they have to be infinite both, so we
1459| return NaN).
1460 cmpl d2,d0 | are both infinite?
1461 bne 1f | if d0 <> d2 they are not equal
1462 cmpl d3,d1 | if d0 == d2 test d3 and d1
1463 beq Ld$inop | if equal return NaN
14641:
74a35b2b 1465 andl IMM (0x80000000),d7 | get a's sign bit '
0d64f74c
DE
1466 cmpl d4,d0 | test now for infinity
1467 beq Ld$infty | if a is INFINITY return with this sign
74a35b2b 1468 bchg IMM (31),d7 | else we know b is INFINITY and has
0d64f74c
DE
1469 bra Ld$infty | the opposite sign
1470
1471|=============================================================================
1472| __muldf3
1473|=============================================================================
1474
1475| double __muldf3(double, double);
2786eb8d 1476 FUNC(__muldf3)
0d64f74c 1477SYM (__muldf3):
9425fb04 1478#ifndef __mcoldfire__
74a35b2b 1479 link a6,IMM (0)
0d64f74c 1480 moveml d2-d7,sp@-
e82673c4
RK
1481#else
1482 link a6,IMM (-24)
1483 moveml d2-d7,sp@
1484#endif
74a35b2b
KR
1485 movel a6@(8),d0 | get a into d0-d1
1486 movel a6@(12),d1 |
1487 movel a6@(16),d2 | and b into d2-d3
1488 movel a6@(20),d3 |
1489 movel d0,d7 | d7 will hold the sign of the product
1490 eorl d2,d7 |
1491 andl IMM (0x80000000),d7 |
1492 movel d7,a0 | save sign bit into a0
1493 movel IMM (0x7ff00000),d7 | useful constant (+INFINITY)
1494 movel d7,d6 | another (mask for fraction)
1495 notl d6 |
1496 bclr IMM (31),d0 | get rid of a's sign bit '
1497 movel d0,d4 |
1498 orl d1,d4 |
1499 beq Lmuldf$a$0 | branch if a is zero
1500 movel d0,d4 |
1501 bclr IMM (31),d2 | get rid of b's sign bit '
1502 movel d2,d5 |
1503 orl d3,d5 |
1504 beq Lmuldf$b$0 | branch if b is zero
1505 movel d2,d5 |
1506 cmpl d7,d0 | is a big?
1507 bhi Lmuldf$inop | if a is NaN return NaN
1508 beq Lmuldf$a$nf | we still have to check d1 and b ...
1509 cmpl d7,d2 | now compare b with INFINITY
1510 bhi Lmuldf$inop | is b NaN?
1511 beq Lmuldf$b$nf | we still have to check d3 ...
0d64f74c
DE
1512| Here we have both numbers finite and nonzero (and with no sign bit).
1513| Now we get the exponents into d4 and d5.
74a35b2b
KR
1514 andl d7,d4 | isolate exponent in d4
1515 beq Lmuldf$a$den | if exponent zero, have denormalized
1516 andl d6,d0 | isolate fraction
1517 orl IMM (0x00100000),d0 | and put hidden bit back
1518 swap d4 | I like exponents in the first byte
9425fb04 1519#ifndef __mcoldfire__
74a35b2b 1520 lsrw IMM (4),d4 |
686cada4
ILT
1521#else
1522 lsrl IMM (4),d4 |
1523#endif
0d64f74c 1524Lmuldf$1:
74a35b2b
KR
1525 andl d7,d5 |
1526 beq Lmuldf$b$den |
1527 andl d6,d2 |
1528 orl IMM (0x00100000),d2 | and put hidden bit back
1529 swap d5 |
9425fb04 1530#ifndef __mcoldfire__
74a35b2b 1531 lsrw IMM (4),d5 |
686cada4
ILT
1532#else
1533 lsrl IMM (4),d5 |
1534#endif
74a35b2b 1535Lmuldf$2: |
9425fb04 1536#ifndef __mcoldfire__
74a35b2b 1537 addw d5,d4 | add exponents
ddd5a7c1 1538 subw IMM (D_BIAS+1),d4 | and subtract bias (plus one)
686cada4
ILT
1539#else
1540 addl d5,d4 | add exponents
1541 subl IMM (D_BIAS+1),d4 | and subtract bias (plus one)
1542#endif
0d64f74c
DE
1543
1544| We are now ready to do the multiplication. The situation is as follows:
1545| both a and b have bit 52 ( bit 20 of d0 and d2) set (even if they were
1546| denormalized to start with!), which means that in the product bit 104
1547| (which will correspond to bit 8 of the fourth long) is set.
1548
1549| Here we have to do the product.
1550| To do it we have to juggle the registers back and forth, as there are not
1551| enough to keep everything in them. So we use the address registers to keep
1552| some intermediate data.
1553
9425fb04 1554#ifndef __mcoldfire__
0d64f74c 1555 moveml a2-a3,sp@- | save a2 and a3 for temporary use
686cada4 1556#else
e82673c4
RK
1557 movel a2,sp@-
1558 movel a3,sp@-
1559 movel a4,sp@-
686cada4 1560#endif
74a35b2b 1561 movel IMM (0),a2 | a2 is a null register
0d64f74c
DE
1562 movel d4,a3 | and a3 will preserve the exponent
1563
1564| First, shift d2-d3 so bit 20 becomes bit 31:
9425fb04 1565#ifndef __mcoldfire__
74a35b2b 1566 rorl IMM (5),d2 | rotate d2 5 places right
0d64f74c 1567 swap d2 | and swap it
74a35b2b 1568 rorl IMM (5),d3 | do the same thing with d3
0d64f74c
DE
1569 swap d3 |
1570 movew d3,d6 | get the rightmost 11 bits of d3
74a35b2b 1571 andw IMM (0x07ff),d6 |
0d64f74c 1572 orw d6,d2 | and put them into d2
74a35b2b 1573 andw IMM (0xf800),d3 | clear those bits in d3
686cada4
ILT
1574#else
1575 moveq IMM (11),d7 | left shift d2 11 bits
1576 lsll d7,d2
1577 movel d3,d6 | get a copy of d3
1578 lsll d7,d3 | left shift d3 11 bits
1579 andl IMM (0xffe00000),d6 | get the top 11 bits of d3
1580 moveq IMM (21),d7 | right shift them 21 bits
1581 lsrl d7,d6
1582 orl d6,d2 | stick them at the end of d2
1583#endif
0d64f74c
DE
1584
1585 movel d2,d6 | move b into d6-d7
1586 movel d3,d7 | move a into d4-d5
1587 movel d0,d4 | and clear d0-d1-d2-d3 (to put result)
1588 movel d1,d5 |
74a35b2b 1589 movel IMM (0),d3 |
0d64f74c
DE
1590 movel d3,d2 |
1591 movel d3,d1 |
1592 movel d3,d0 |
1593
1594| We use a1 as counter:
74a35b2b 1595 movel IMM (DBL_MANT_DIG-1),a1
9425fb04 1596#ifndef __mcoldfire__
0d64f74c 1597 exg d7,a1
686cada4
ILT
1598#else
1599 movel d7,a4
1600 movel a1,d7
1601 movel a4,a1
1602#endif
0d64f74c 1603
686cada4 16041:
9425fb04 1605#ifndef __mcoldfire__
686cada4
ILT
1606 exg d7,a1 | put counter back in a1
1607#else
1608 movel d7,a4
1609 movel a1,d7
1610 movel a4,a1
1611#endif
0d64f74c
DE
1612 addl d3,d3 | shift sum once left
1613 addxl d2,d2 |
1614 addxl d1,d1 |
1615 addxl d0,d0 |
1616 addl d7,d7 |
1617 addxl d6,d6 |
1618 bcc 2f | if bit clear skip the following
9425fb04 1619#ifndef __mcoldfire__
0d64f74c 1620 exg d7,a2 |
686cada4
ILT
1621#else
1622 movel d7,a4
1623 movel a2,d7
1624 movel a4,a2
1625#endif
0d64f74c
DE
1626 addl d5,d3 | else add a to the sum
1627 addxl d4,d2 |
1628 addxl d7,d1 |
1629 addxl d7,d0 |
9425fb04 1630#ifndef __mcoldfire__
0d64f74c 1631 exg d7,a2 |
686cada4
ILT
1632#else
1633 movel d7,a4
1634 movel a2,d7
1635 movel a4,a2
1636#endif
16372:
9425fb04 1638#ifndef __mcoldfire__
686cada4 1639 exg d7,a1 | put counter in d7
0d64f74c 1640 dbf d7,1b | decrement and branch
686cada4
ILT
1641#else
1642 movel d7,a4
1643 movel a1,d7
1644 movel a4,a1
1645 subql IMM (1),d7
1646 bpl 1b
1647#endif
0d64f74c
DE
1648
1649 movel a3,d4 | restore exponent
9425fb04 1650#ifndef __mcoldfire__
0d64f74c 1651 moveml sp@+,a2-a3
686cada4 1652#else
e82673c4
RK
1653 movel sp@+,a4
1654 movel sp@+,a3
1655 movel sp@+,a2
686cada4 1656#endif
0d64f74c
DE
1657
1658| Now we have the product in d0-d1-d2-d3, with bit 8 of d0 set. The
1659| first thing to do now is to normalize it so bit 8 becomes bit
1660| DBL_MANT_DIG-32 (to do the rounding); later we will shift right.
1661 swap d0
1662 swap d1
1663 movew d1,d0
1664 swap d2
1665 movew d2,d1
1666 swap d3
1667 movew d3,d2
74a35b2b 1668 movew IMM (0),d3
9425fb04 1669#ifndef __mcoldfire__
74a35b2b
KR
1670 lsrl IMM (1),d0
1671 roxrl IMM (1),d1
1672 roxrl IMM (1),d2
1673 roxrl IMM (1),d3
1674 lsrl IMM (1),d0
1675 roxrl IMM (1),d1
1676 roxrl IMM (1),d2
1677 roxrl IMM (1),d3
1678 lsrl IMM (1),d0
1679 roxrl IMM (1),d1
1680 roxrl IMM (1),d2
1681 roxrl IMM (1),d3
686cada4
ILT
1682#else
1683 moveq IMM (29),d6
1684 lsrl IMM (3),d3
1685 movel d2,d7
1686 lsll d6,d7
1687 orl d7,d3
1688 lsrl IMM (3),d2
1689 movel d1,d7
1690 lsll d6,d7
1691 orl d7,d2
1692 lsrl IMM (3),d1
1693 movel d0,d7
1694 lsll d6,d7
1695 orl d7,d1
1696 lsrl IMM (3),d0
1697#endif
0d64f74c
DE
1698
1699| Now round, check for over- and underflow, and exit.
1700 movel a0,d7 | get sign bit back into d7
aa2192f8 1701 moveq IMM (MULTIPLY),d5
0d64f74c 1702
74a35b2b 1703 btst IMM (DBL_MANT_DIG+1-32),d0
0d64f74c 1704 beq Lround$exit
9425fb04 1705#ifndef __mcoldfire__
74a35b2b
KR
1706 lsrl IMM (1),d0
1707 roxrl IMM (1),d1
1708 addw IMM (1),d4
686cada4
ILT
1709#else
1710 lsrl IMM (1),d1
1711 btst IMM (0),d0
1712 beq 10f
1713 bset IMM (31),d1
171410: lsrl IMM (1),d0
1715 addl IMM (1),d4
1716#endif
0d64f74c
DE
1717 bra Lround$exit
1718
1719Lmuldf$inop:
aa2192f8 1720 moveq IMM (MULTIPLY),d5
0d64f74c
DE
1721 bra Ld$inop
1722
1723Lmuldf$b$nf:
aa2192f8 1724 moveq IMM (MULTIPLY),d5
0d64f74c
DE
1725 movel a0,d7 | get sign bit back into d7
1726 tstl d3 | we know d2 == 0x7ff00000, so check d3
1727 bne Ld$inop | if d3 <> 0 b is NaN
1728 bra Ld$overflow | else we have overflow (since a is finite)
1729
1730Lmuldf$a$nf:
aa2192f8 1731 moveq IMM (MULTIPLY),d5
0d64f74c
DE
1732 movel a0,d7 | get sign bit back into d7
1733 tstl d1 | we know d0 == 0x7ff00000, so check d1
1734 bne Ld$inop | if d1 <> 0 a is NaN
1735 bra Ld$overflow | else signal overflow
1736
1737| If either number is zero return zero, unless the other is +/-INFINITY or
1738| NaN, in which case we return NaN.
1739Lmuldf$b$0:
aa2192f8 1740 moveq IMM (MULTIPLY),d5
9425fb04 1741#ifndef __mcoldfire__
0d64f74c
DE
1742 exg d2,d0 | put b (==0) into d0-d1
1743 exg d3,d1 | and a (with sign bit cleared) into d2-d3
d55f9d23 1744 movel a0,d0 | set result sign
686cada4 1745#else
d55f9d23 1746 movel d0,d2 | put a into d2-d3
686cada4 1747 movel d1,d3
d55f9d23
NS
1748 movel a0,d0 | put result zero into d0-d1
1749 movq IMM(0),d1
686cada4 1750#endif
0d64f74c
DE
1751 bra 1f
1752Lmuldf$a$0:
d55f9d23 1753 movel a0,d0 | set result sign
0d64f74c
DE
1754 movel a6@(16),d2 | put b into d2-d3 again
1755 movel a6@(20),d3 |
74a35b2b
KR
1756 bclr IMM (31),d2 | clear sign bit
17571: cmpl IMM (0x7ff00000),d2 | check for non-finiteness
0d64f74c 1758 bge Ld$inop | in case NaN or +/-INFINITY return NaN
a2ef3db7 1759 PICLEA SYM (_fpCCR),a0
74a35b2b 1760 movew IMM (0),a0@
9425fb04 1761#ifndef __mcoldfire__
0d64f74c 1762 moveml sp@+,d2-d7
e82673c4
RK
1763#else
1764 moveml sp@,d2-d7
1765 | XXX if frame pointer is ever removed, stack pointer must
1766 | be adjusted here.
1767#endif
0d64f74c
DE
1768 unlk a6
1769 rts
1770
1771| If a number is denormalized we put an exponent of 1 but do not put the
1772| hidden bit back into the fraction; instead we shift left until bit 21
1773| (the hidden bit) is set, adjusting the exponent accordingly. We do this
1774| to ensure that the product of the fractions is close to 1.
1775Lmuldf$a$den:
74a35b2b 1776 movel IMM (1),d4
0d64f74c
DE
1777 andl d6,d0
17781: addl d1,d1 | shift a left until bit 20 is set
1779 addxl d0,d0 |
9425fb04 1780#ifndef __mcoldfire__
74a35b2b 1781 subw IMM (1),d4 | and adjust exponent
686cada4
ILT
1782#else
1783 subl IMM (1),d4 | and adjust exponent
1784#endif
74a35b2b 1785 btst IMM (20),d0 |
0d64f74c
DE
1786 bne Lmuldf$1 |
1787 bra 1b
1788
1789Lmuldf$b$den:
74a35b2b 1790 movel IMM (1),d5
0d64f74c
DE
1791 andl d6,d2
17921: addl d3,d3 | shift b left until bit 20 is set
1793 addxl d2,d2 |
9425fb04 1794#ifndef __mcoldfire__
74a35b2b 1795 subw IMM (1),d5 | and adjust exponent
686cada4
ILT
1796#else
1797 subql IMM (1),d5 | and adjust exponent
1798#endif
74a35b2b 1799 btst IMM (20),d2 |
0d64f74c
DE
1800 bne Lmuldf$2 |
1801 bra 1b
1802
1803
1804|=============================================================================
1805| __divdf3
1806|=============================================================================
1807
1808| double __divdf3(double, double);
2786eb8d 1809 FUNC(__divdf3)
0d64f74c 1810SYM (__divdf3):
9425fb04 1811#ifndef __mcoldfire__
74a35b2b 1812 link a6,IMM (0)
0d64f74c 1813 moveml d2-d7,sp@-
e82673c4
RK
1814#else
1815 link a6,IMM (-24)
1816 moveml d2-d7,sp@
1817#endif
0d64f74c
DE
1818 movel a6@(8),d0 | get a into d0-d1
1819 movel a6@(12),d1 |
1820 movel a6@(16),d2 | and b into d2-d3
1821 movel a6@(20),d3 |
1822 movel d0,d7 | d7 will hold the sign of the result
1823 eorl d2,d7 |
74a35b2b 1824 andl IMM (0x80000000),d7
0d64f74c 1825 movel d7,a0 | save sign into a0
74a35b2b 1826 movel IMM (0x7ff00000),d7 | useful constant (+INFINITY)
0d64f74c
DE
1827 movel d7,d6 | another (mask for fraction)
1828 notl d6 |
74a35b2b 1829 bclr IMM (31),d0 | get rid of a's sign bit '
0d64f74c
DE
1830 movel d0,d4 |
1831 orl d1,d4 |
1832 beq Ldivdf$a$0 | branch if a is zero
1833 movel d0,d4 |
74a35b2b 1834 bclr IMM (31),d2 | get rid of b's sign bit '
0d64f74c
DE
1835 movel d2,d5 |
1836 orl d3,d5 |
1837 beq Ldivdf$b$0 | branch if b is zero
1838 movel d2,d5
1839 cmpl d7,d0 | is a big?
1840 bhi Ldivdf$inop | if a is NaN return NaN
1841 beq Ldivdf$a$nf | if d0 == 0x7ff00000 we check d1
1842 cmpl d7,d2 | now compare b with INFINITY
1843 bhi Ldivdf$inop | if b is NaN return NaN
1844 beq Ldivdf$b$nf | if d2 == 0x7ff00000 we check d3
1845| Here we have both numbers finite and nonzero (and with no sign bit).
1846| Now we get the exponents into d4 and d5 and normalize the numbers to
1847| ensure that the ratio of the fractions is around 1. We do this by
1848| making sure that both numbers have bit #DBL_MANT_DIG-32-1 (hidden bit)
1849| set, even if they were denormalized to start with.
1850| Thus, the result will satisfy: 2 > result > 1/2.
1851 andl d7,d4 | and isolate exponent in d4
1852 beq Ldivdf$a$den | if exponent is zero we have a denormalized
1853 andl d6,d0 | and isolate fraction
74a35b2b 1854 orl IMM (0x00100000),d0 | and put hidden bit back
0d64f74c 1855 swap d4 | I like exponents in the first byte
9425fb04 1856#ifndef __mcoldfire__
74a35b2b 1857 lsrw IMM (4),d4 |
686cada4
ILT
1858#else
1859 lsrl IMM (4),d4 |
1860#endif
0d64f74c
DE
1861Ldivdf$1: |
1862 andl d7,d5 |
1863 beq Ldivdf$b$den |
1864 andl d6,d2 |
74a35b2b 1865 orl IMM (0x00100000),d2
0d64f74c 1866 swap d5 |
9425fb04 1867#ifndef __mcoldfire__
74a35b2b 1868 lsrw IMM (4),d5 |
686cada4
ILT
1869#else
1870 lsrl IMM (4),d5 |
1871#endif
0d64f74c 1872Ldivdf$2: |
9425fb04 1873#ifndef __mcoldfire__
ddd5a7c1 1874 subw d5,d4 | subtract exponents
74a35b2b 1875 addw IMM (D_BIAS),d4 | and add bias
686cada4
ILT
1876#else
1877 subl d5,d4 | subtract exponents
1878 addl IMM (D_BIAS),d4 | and add bias
1879#endif
0d64f74c
DE
1880
1881| We are now ready to do the division. We have prepared things in such a way
1882| that the ratio of the fractions will be less than 2 but greater than 1/2.
1883| At this point the registers in use are:
1884| d0-d1 hold a (first operand, bit DBL_MANT_DIG-32=0, bit
1885| DBL_MANT_DIG-1-32=1)
1886| d2-d3 hold b (second operand, bit DBL_MANT_DIG-32=1)
1887| d4 holds the difference of the exponents, corrected by the bias
1888| a0 holds the sign of the ratio
1889
1890| To do the rounding correctly we need to keep information about the
1891| nonsignificant bits. One way to do this would be to do the division
1892| using four registers; another is to use two registers (as originally
1893| I did), but use a sticky bit to preserve information about the
1894| fractional part. Note that we can keep that info in a1, which is not
1895| used.
74a35b2b 1896 movel IMM (0),d6 | d6-d7 will hold the result
0d64f74c 1897 movel d6,d7 |
74a35b2b 1898 movel IMM (0),a1 | and a1 will hold the sticky bit
0d64f74c 1899
74a35b2b 1900 movel IMM (DBL_MANT_DIG-32+1),d5
0d64f74c
DE
1901
19021: cmpl d0,d2 | is a < b?
1903 bhi 3f | if b > a skip the following
1904 beq 4f | if d0==d2 check d1 and d3
19052: subl d3,d1 |
1906 subxl d2,d0 | a <-- a - b
1907 bset d5,d6 | set the corresponding bit in d6
19083: addl d1,d1 | shift a by 1
1909 addxl d0,d0 |
9425fb04 1910#ifndef __mcoldfire__
0d64f74c 1911 dbra d5,1b | and branch back
686cada4
ILT
1912#else
1913 subql IMM (1), d5
1914 bpl 1b
1915#endif
0d64f74c
DE
1916 bra 5f
19174: cmpl d1,d3 | here d0==d2, so check d1 and d3
ddd5a7c1 1918 bhi 3b | if d1 > d2 skip the subtraction
0d64f74c
DE
1919 bra 2b | else go do it
19205:
1921| Here we have to start setting the bits in the second long.
74a35b2b 1922 movel IMM (31),d5 | again d5 is counter
0d64f74c
DE
1923
19241: cmpl d0,d2 | is a < b?
1925 bhi 3f | if b > a skip the following
1926 beq 4f | if d0==d2 check d1 and d3
19272: subl d3,d1 |
1928 subxl d2,d0 | a <-- a - b
1929 bset d5,d7 | set the corresponding bit in d7
19303: addl d1,d1 | shift a by 1
1931 addxl d0,d0 |
9425fb04 1932#ifndef __mcoldfire__
0d64f74c 1933 dbra d5,1b | and branch back
686cada4
ILT
1934#else
1935 subql IMM (1), d5
1936 bpl 1b
1937#endif
0d64f74c
DE
1938 bra 5f
19394: cmpl d1,d3 | here d0==d2, so check d1 and d3
ddd5a7c1 1940 bhi 3b | if d1 > d2 skip the subtraction
0d64f74c
DE
1941 bra 2b | else go do it
19425:
1943| Now go ahead checking until we hit a one, which we store in d2.
74a35b2b 1944 movel IMM (DBL_MANT_DIG),d5
0d64f74c
DE
19451: cmpl d2,d0 | is a < b?
1946 bhi 4f | if b < a, exit
1947 beq 3f | if d0==d2 check d1 and d3
19482: addl d1,d1 | shift a by 1
1949 addxl d0,d0 |
9425fb04 1950#ifndef __mcoldfire__
0d64f74c 1951 dbra d5,1b | and branch back
686cada4
ILT
1952#else
1953 subql IMM (1), d5
1954 bpl 1b
1955#endif
74a35b2b 1956 movel IMM (0),d2 | here no sticky bit was found
0d64f74c
DE
1957 movel d2,d3
1958 bra 5f
19593: cmpl d1,d3 | here d0==d2, so check d1 and d3
1960 bhi 2b | if d1 > d2 go back
19614:
1962| Here put the sticky bit in d2-d3 (in the position which actually corresponds
1963| to it; if you don't do this the algorithm loses in some cases). '
74a35b2b 1964 movel IMM (0),d2
0d64f74c 1965 movel d2,d3
9425fb04 1966#ifndef __mcoldfire__
74a35b2b
KR
1967 subw IMM (DBL_MANT_DIG),d5
1968 addw IMM (63),d5
1969 cmpw IMM (31),d5
686cada4
ILT
1970#else
1971 subl IMM (DBL_MANT_DIG),d5
1972 addl IMM (63),d5
1973 cmpl IMM (31),d5
1974#endif
0d64f74c
DE
1975 bhi 2f
19761: bset d5,d3
1977 bra 5f
9425fb04 1978#ifndef __mcoldfire__
74a35b2b 1979 subw IMM (32),d5
686cada4
ILT
1980#else
1981 subl IMM (32),d5
1982#endif
0d64f74c
DE
19832: bset d5,d2
19845:
1985| Finally we are finished! Move the longs in the address registers to
1986| their final destination:
1987 movel d6,d0
1988 movel d7,d1
74a35b2b 1989 movel IMM (0),d3
0d64f74c
DE
1990
1991| Here we have finished the division, with the result in d0-d1-d2-d3, with
1992| 2^21 <= d6 < 2^23. Thus bit 23 is not set, but bit 22 could be set.
1993| If it is not, then definitely bit 21 is set. Normalize so bit 22 is
1994| not set:
74a35b2b 1995 btst IMM (DBL_MANT_DIG-32+1),d0
0d64f74c 1996 beq 1f
9425fb04 1997#ifndef __mcoldfire__
74a35b2b
KR
1998 lsrl IMM (1),d0
1999 roxrl IMM (1),d1
2000 roxrl IMM (1),d2
2001 roxrl IMM (1),d3
2002 addw IMM (1),d4
686cada4
ILT
2003#else
2004 lsrl IMM (1),d3
2005 btst IMM (0),d2
2006 beq 10f
2007 bset IMM (31),d3
200810: lsrl IMM (1),d2
2009 btst IMM (0),d1
2010 beq 11f
2011 bset IMM (31),d2
201211: lsrl IMM (1),d1
2013 btst IMM (0),d0
2014 beq 12f
2015 bset IMM (31),d1
201612: lsrl IMM (1),d0
2017 addl IMM (1),d4
2018#endif
0d64f74c
DE
20191:
2020| Now round, check for over- and underflow, and exit.
2021 movel a0,d7 | restore sign bit to d7
aa2192f8 2022 moveq IMM (DIVIDE),d5
0d64f74c
DE
2023 bra Lround$exit
2024
2025Ldivdf$inop:
aa2192f8 2026 moveq IMM (DIVIDE),d5
0d64f74c
DE
2027 bra Ld$inop
2028
2029Ldivdf$a$0:
2030| If a is zero check to see whether b is zero also. In that case return
2031| NaN; then check if b is NaN, and return NaN also in that case. Else
d55f9d23 2032| return a properly signed zero.
aa2192f8 2033 moveq IMM (DIVIDE),d5
74a35b2b 2034 bclr IMM (31),d2 |
0d64f74c
DE
2035 movel d2,d4 |
2036 orl d3,d4 |
2037 beq Ld$inop | if b is also zero return NaN
74a35b2b 2038 cmpl IMM (0x7ff00000),d2 | check for NaN
0d64f74c
DE
2039 bhi Ld$inop |
2040 blt 1f |
2041 tstl d3 |
2042 bne Ld$inop |
d55f9d23
NS
20431: movel a0,d0 | else return signed zero
2044 moveq IMM(0),d1 |
a2ef3db7 2045 PICLEA SYM (_fpCCR),a0 | clear exception flags
74a35b2b 2046 movew IMM (0),a0@ |
9425fb04 2047#ifndef __mcoldfire__
0d64f74c 2048 moveml sp@+,d2-d7 |
e82673c4
RK
2049#else
2050 moveml sp@,d2-d7 |
2051 | XXX if frame pointer is ever removed, stack pointer must
2052 | be adjusted here.
2053#endif
0d64f74c
DE
2054 unlk a6 |
2055 rts |
2056
2057Ldivdf$b$0:
aa2192f8 2058 moveq IMM (DIVIDE),d5
0d64f74c
DE
2059| If we got here a is not zero. Check if a is NaN; in that case return NaN,
2060| else return +/-INFINITY. Remember that a is in d0 with the sign bit
2061| cleared already.
2062 movel a0,d7 | put a's sign bit back in d7 '
74a35b2b 2063 cmpl IMM (0x7ff00000),d0 | compare d0 with INFINITY
0d64f74c
DE
2064 bhi Ld$inop | if larger it is NaN
2065 tstl d1 |
2066 bne Ld$inop |
2067 bra Ld$div$0 | else signal DIVIDE_BY_ZERO
2068
2069Ldivdf$b$nf:
aa2192f8 2070 moveq IMM (DIVIDE),d5
0d64f74c
DE
2071| If d2 == 0x7ff00000 we have to check d3.
2072 tstl d3 |
2073 bne Ld$inop | if d3 <> 0, b is NaN
2074 bra Ld$underflow | else b is +/-INFINITY, so signal underflow
2075
2076Ldivdf$a$nf:
aa2192f8 2077 moveq IMM (DIVIDE),d5
0d64f74c
DE
2078| If d0 == 0x7ff00000 we have to check d1.
2079 tstl d1 |
2080 bne Ld$inop | if d1 <> 0, a is NaN
2081| If a is INFINITY we have to check b
2082 cmpl d7,d2 | compare b with INFINITY
2083 bge Ld$inop | if b is NaN or INFINITY return NaN
2084 tstl d3 |
2085 bne Ld$inop |
2086 bra Ld$overflow | else return overflow
2087
2088| If a number is denormalized we put an exponent of 1 but do not put the
2089| bit back into the fraction.
2090Ldivdf$a$den:
74a35b2b 2091 movel IMM (1),d4
0d64f74c
DE
2092 andl d6,d0
20931: addl d1,d1 | shift a left until bit 20 is set
2094 addxl d0,d0
9425fb04 2095#ifndef __mcoldfire__
74a35b2b 2096 subw IMM (1),d4 | and adjust exponent
686cada4
ILT
2097#else
2098 subl IMM (1),d4 | and adjust exponent
2099#endif
74a35b2b 2100 btst IMM (DBL_MANT_DIG-32-1),d0
0d64f74c
DE
2101 bne Ldivdf$1
2102 bra 1b
2103
2104Ldivdf$b$den:
74a35b2b 2105 movel IMM (1),d5
0d64f74c
DE
2106 andl d6,d2
21071: addl d3,d3 | shift b left until bit 20 is set
2108 addxl d2,d2
9425fb04 2109#ifndef __mcoldfire__
74a35b2b 2110 subw IMM (1),d5 | and adjust exponent
686cada4
ILT
2111#else
2112 subql IMM (1),d5 | and adjust exponent
2113#endif
74a35b2b 2114 btst IMM (DBL_MANT_DIG-32-1),d2
0d64f74c
DE
2115 bne Ldivdf$2
2116 bra 1b
2117
2118Lround$exit:
2119| This is a common exit point for __muldf3 and __divdf3. When they enter
2120| this point the sign of the result is in d7, the result in d0-d1, normalized
2121| so that 2^21 <= d0 < 2^22, and the exponent is in the lower byte of d4.
2122
2123| First check for underlow in the exponent:
9425fb04 2124#ifndef __mcoldfire__
74a35b2b 2125 cmpw IMM (-DBL_MANT_DIG-1),d4
686cada4
ILT
2126#else
2127 cmpl IMM (-DBL_MANT_DIG-1),d4
2128#endif
0d64f74c
DE
2129 blt Ld$underflow
2130| It could happen that the exponent is less than 1, in which case the
2131| number is denormalized. In this case we shift right and adjust the
2132| exponent until it becomes 1 or the fraction is zero (in the latter case
2133| we signal underflow and return zero).
2134 movel d7,a0 |
74a35b2b 2135 movel IMM (0),d6 | use d6-d7 to collect bits flushed right
0d64f74c 2136 movel d6,d7 | use d6-d7 to collect bits flushed right
9425fb04 2137#ifndef __mcoldfire__
74a35b2b 2138 cmpw IMM (1),d4 | if the exponent is less than 1 we
686cada4
ILT
2139#else
2140 cmpl IMM (1),d4 | if the exponent is less than 1 we
2141#endif
0d64f74c 2142 bge 2f | have to shift right (denormalize)
686cada4 21431:
9425fb04 2144#ifndef __mcoldfire__
686cada4 2145 addw IMM (1),d4 | adjust the exponent
74a35b2b
KR
2146 lsrl IMM (1),d0 | shift right once
2147 roxrl IMM (1),d1 |
2148 roxrl IMM (1),d2 |
2149 roxrl IMM (1),d3 |
2150 roxrl IMM (1),d6 |
2151 roxrl IMM (1),d7 |
2152 cmpw IMM (1),d4 | is the exponent 1 already?
686cada4
ILT
2153#else
2154 addl IMM (1),d4 | adjust the exponent
2155 lsrl IMM (1),d7
2156 btst IMM (0),d6
2157 beq 13f
2158 bset IMM (31),d7
215913: lsrl IMM (1),d6
2160 btst IMM (0),d3
2161 beq 14f
2162 bset IMM (31),d6
216314: lsrl IMM (1),d3
2164 btst IMM (0),d2
2165 beq 10f
2166 bset IMM (31),d3
216710: lsrl IMM (1),d2
2168 btst IMM (0),d1
2169 beq 11f
2170 bset IMM (31),d2
217111: lsrl IMM (1),d1
2172 btst IMM (0),d0
2173 beq 12f
2174 bset IMM (31),d1
217512: lsrl IMM (1),d0
2176 cmpl IMM (1),d4 | is the exponent 1 already?
2177#endif
0d64f74c
DE
2178 beq 2f | if not loop back
2179 bra 1b |
2180 bra Ld$underflow | safety check, shouldn't execute '
21812: orl d6,d2 | this is a trick so we don't lose '
2182 orl d7,d3 | the bits which were flushed right
2183 movel a0,d7 | get back sign bit into d7
2184| Now call the rounding routine (which takes care of denormalized numbers):
a2ef3db7
BI
2185 lea pc@(Lround$0),a0 | to return from rounding routine
2186 PICLEA SYM (_fpCCR),a1 | check the rounding mode
9425fb04 2187#ifdef __mcoldfire__
686cada4
ILT
2188 clrl d6
2189#endif
0d64f74c
DE
2190 movew a1@(6),d6 | rounding mode in d6
2191 beq Lround$to$nearest
9425fb04 2192#ifndef __mcoldfire__
74a35b2b 2193 cmpw IMM (ROUND_TO_PLUS),d6
686cada4
ILT
2194#else
2195 cmpl IMM (ROUND_TO_PLUS),d6
2196#endif
0d64f74c
DE
2197 bhi Lround$to$minus
2198 blt Lround$to$zero
2199 bra Lround$to$plus
2200Lround$0:
2201| Here we have a correctly rounded result (either normalized or denormalized).
2202
2203| Here we should have either a normalized number or a denormalized one, and
2204| the exponent is necessarily larger or equal to 1 (so we don't have to '
2205| check again for underflow!). We have to check for overflow or for a
2206| denormalized number (which also signals underflow).
2207| Check for overflow (i.e., exponent >= 0x7ff).
9425fb04 2208#ifndef __mcoldfire__
74a35b2b 2209 cmpw IMM (0x07ff),d4
686cada4
ILT
2210#else
2211 cmpl IMM (0x07ff),d4
2212#endif
0d64f74c
DE
2213 bge Ld$overflow
2214| Now check for a denormalized number (exponent==0):
2215 movew d4,d4
2216 beq Ld$den
22171:
2218| Put back the exponents and sign and return.
9425fb04 2219#ifndef __mcoldfire__
74a35b2b 2220 lslw IMM (4),d4 | exponent back to fourth byte
686cada4
ILT
2221#else
2222 lsll IMM (4),d4 | exponent back to fourth byte
2223#endif
74a35b2b 2224 bclr IMM (DBL_MANT_DIG-32-1),d0
0d64f74c 2225 swap d0 | and put back exponent
9425fb04 2226#ifndef __mcoldfire__
0d64f74c 2227 orw d4,d0 |
686cada4
ILT
2228#else
2229 orl d4,d0 |
2230#endif
0d64f74c
DE
2231 swap d0 |
2232 orl d7,d0 | and sign also
2233
a2ef3db7 2234 PICLEA SYM (_fpCCR),a0
74a35b2b 2235 movew IMM (0),a0@
9425fb04 2236#ifndef __mcoldfire__
0d64f74c 2237 moveml sp@+,d2-d7
e82673c4
RK
2238#else
2239 moveml sp@,d2-d7
2240 | XXX if frame pointer is ever removed, stack pointer must
2241 | be adjusted here.
2242#endif
0d64f74c
DE
2243 unlk a6
2244 rts
2245
2246|=============================================================================
2247| __negdf2
2248|=============================================================================
2249
2250| double __negdf2(double, double);
2786eb8d 2251 FUNC(__negdf2)
0d64f74c 2252SYM (__negdf2):
9425fb04 2253#ifndef __mcoldfire__
74a35b2b 2254 link a6,IMM (0)
0d64f74c 2255 moveml d2-d7,sp@-
e82673c4
RK
2256#else
2257 link a6,IMM (-24)
2258 moveml d2-d7,sp@
2259#endif
aa2192f8 2260 moveq IMM (NEGATE),d5
0d64f74c
DE
2261 movel a6@(8),d0 | get number to negate in d0-d1
2262 movel a6@(12),d1 |
74a35b2b 2263 bchg IMM (31),d0 | negate
0d64f74c 2264 movel d0,d2 | make a positive copy (for the tests)
74a35b2b 2265 bclr IMM (31),d2 |
0d64f74c
DE
2266 movel d2,d4 | check for zero
2267 orl d1,d4 |
2268 beq 2f | if zero (either sign) return +zero
74a35b2b 2269 cmpl IMM (0x7ff00000),d2 | compare to +INFINITY
0d64f74c
DE
2270 blt 1f | if finite, return
2271 bhi Ld$inop | if larger (fraction not zero) is NaN
2272 tstl d1 | if d2 == 0x7ff00000 check d1
2273 bne Ld$inop |
2274 movel d0,d7 | else get sign and return INFINITY
74a35b2b 2275 andl IMM (0x80000000),d7
0d64f74c 2276 bra Ld$infty
a2ef3db7 22771: PICLEA SYM (_fpCCR),a0
74a35b2b 2278 movew IMM (0),a0@
9425fb04 2279#ifndef __mcoldfire__
0d64f74c 2280 moveml sp@+,d2-d7
e82673c4
RK
2281#else
2282 moveml sp@,d2-d7
2283 | XXX if frame pointer is ever removed, stack pointer must
2284 | be adjusted here.
2285#endif
0d64f74c
DE
2286 unlk a6
2287 rts
74a35b2b 22882: bclr IMM (31),d0
0d64f74c
DE
2289 bra 1b
2290
2291|=============================================================================
2292| __cmpdf2
2293|=============================================================================
2294
2295GREATER = 1
2296LESS = -1
2297EQUAL = 0
2298
1a50d5e9
PB
2299| int __cmpdf2_internal(double, double, int);
2300SYM (__cmpdf2_internal):
9425fb04 2301#ifndef __mcoldfire__
74a35b2b 2302 link a6,IMM (0)
0d64f74c 2303 moveml d2-d7,sp@- | save registers
e82673c4
RK
2304#else
2305 link a6,IMM (-24)
2306 moveml d2-d7,sp@
2307#endif
aa2192f8 2308 moveq IMM (COMPARE),d5
0d64f74c
DE
2309 movel a6@(8),d0 | get first operand
2310 movel a6@(12),d1 |
2311 movel a6@(16),d2 | get second operand
2312 movel a6@(20),d3 |
2313| First check if a and/or b are (+/-) zero and in that case clear
2314| the sign bit.
2315 movel d0,d6 | copy signs into d6 (a) and d7(b)
74a35b2b 2316 bclr IMM (31),d0 | and clear signs in d0 and d2
0d64f74c 2317 movel d2,d7 |
74a35b2b 2318 bclr IMM (31),d2 |
1a50d5e9
PB
2319 cmpl IMM (0x7ff00000),d0 | check for a == NaN
2320 bhi Lcmpd$inop | if d0 > 0x7ff00000, a is NaN
0d64f74c
DE
2321 beq Lcmpdf$a$nf | if equal can be INFINITY, so check d1
2322 movel d0,d4 | copy into d4 to test for zero
2323 orl d1,d4 |
2324 beq Lcmpdf$a$0 |
2325Lcmpdf$0:
1a50d5e9
PB
2326 cmpl IMM (0x7ff00000),d2 | check for b == NaN
2327 bhi Lcmpd$inop | if d2 > 0x7ff00000, b is NaN
0d64f74c
DE
2328 beq Lcmpdf$b$nf | if equal can be INFINITY, so check d3
2329 movel d2,d4 |
2330 orl d3,d4 |
2331 beq Lcmpdf$b$0 |
2332Lcmpdf$1:
2333| Check the signs
2334 eorl d6,d7
2335 bpl 1f
2336| If the signs are not equal check if a >= 0
2337 tstl d6
2338 bpl Lcmpdf$a$gt$b | if (a >= 0 && b < 0) => a > b
2339 bmi Lcmpdf$b$gt$a | if (a < 0 && b >= 0) => a < b
23401:
2341| If the signs are equal check for < 0
2342 tstl d6
2343 bpl 1f
2344| If both are negative exchange them
9425fb04 2345#ifndef __mcoldfire__
0d64f74c
DE
2346 exg d0,d2
2347 exg d1,d3
686cada4
ILT
2348#else
2349 movel d0,d7
2350 movel d2,d0
2351 movel d7,d2
2352 movel d1,d7
2353 movel d3,d1
2354 movel d7,d3
2355#endif
0d64f74c
DE
23561:
2357| Now that they are positive we just compare them as longs (does this also
2358| work for denormalized numbers?).
2359 cmpl d0,d2
2360 bhi Lcmpdf$b$gt$a | |b| > |a|
2361 bne Lcmpdf$a$gt$b | |b| < |a|
2362| If we got here d0 == d2, so we compare d1 and d3.
2363 cmpl d1,d3
2364 bhi Lcmpdf$b$gt$a | |b| > |a|
2365 bne Lcmpdf$a$gt$b | |b| < |a|
2366| If we got here a == b.
74a35b2b 2367 movel IMM (EQUAL),d0
9425fb04 2368#ifndef __mcoldfire__
0d64f74c 2369 moveml sp@+,d2-d7 | put back the registers
e82673c4
RK
2370#else
2371 moveml sp@,d2-d7
2372 | XXX if frame pointer is ever removed, stack pointer must
2373 | be adjusted here.
2374#endif
0d64f74c
DE
2375 unlk a6
2376 rts
2377Lcmpdf$a$gt$b:
74a35b2b 2378 movel IMM (GREATER),d0
9425fb04 2379#ifndef __mcoldfire__
0d64f74c 2380 moveml sp@+,d2-d7 | put back the registers
e82673c4
RK
2381#else
2382 moveml sp@,d2-d7
2383 | XXX if frame pointer is ever removed, stack pointer must
2384 | be adjusted here.
2385#endif
0d64f74c
DE
2386 unlk a6
2387 rts
2388Lcmpdf$b$gt$a:
74a35b2b 2389 movel IMM (LESS),d0
9425fb04 2390#ifndef __mcoldfire__
0d64f74c 2391 moveml sp@+,d2-d7 | put back the registers
e82673c4
RK
2392#else
2393 moveml sp@,d2-d7
2394 | XXX if frame pointer is ever removed, stack pointer must
2395 | be adjusted here.
2396#endif
0d64f74c
DE
2397 unlk a6
2398 rts
2399
2400Lcmpdf$a$0:
74a35b2b 2401 bclr IMM (31),d6
0d64f74c
DE
2402 bra Lcmpdf$0
2403Lcmpdf$b$0:
74a35b2b 2404 bclr IMM (31),d7
0d64f74c
DE
2405 bra Lcmpdf$1
2406
2407Lcmpdf$a$nf:
2408 tstl d1
2409 bne Ld$inop
2410 bra Lcmpdf$0
2411
2412Lcmpdf$b$nf:
2413 tstl d3
2414 bne Ld$inop
2415 bra Lcmpdf$1
2416
1a50d5e9
PB
2417Lcmpd$inop:
2418 movl a6@(24),d0
aa2192f8 2419 moveq IMM (INEXACT_RESULT+INVALID_OPERATION),d7
1a50d5e9
PB
2420 moveq IMM (DOUBLE_FLOAT),d6
2421 PICJUMP $_exception_handler
2422
2423| int __cmpdf2(double, double);
2786eb8d 2424 FUNC(__cmpdf2)
1a50d5e9
PB
2425SYM (__cmpdf2):
2426 link a6,IMM (0)
2427 pea 1
2428 movl a6@(20),sp@-
2429 movl a6@(16),sp@-
2430 movl a6@(12),sp@-
2431 movl a6@(8),sp@-
c1af059c 2432 PICCALL SYM (__cmpdf2_internal)
1a50d5e9
PB
2433 unlk a6
2434 rts
2435
0d64f74c
DE
2436|=============================================================================
2437| rounding routines
2438|=============================================================================
2439
2440| The rounding routines expect the number to be normalized in registers
2441| d0-d1-d2-d3, with the exponent in register d4. They assume that the
2442| exponent is larger or equal to 1. They return a properly normalized number
2443| if possible, and a denormalized number otherwise. The exponent is returned
2444| in d4.
2445
2446Lround$to$nearest:
2447| We now normalize as suggested by D. Knuth ("Seminumerical Algorithms"):
2448| Here we assume that the exponent is not too small (this should be checked
2449| before entering the rounding routine), but the number could be denormalized.
2450
2451| Check for denormalized numbers:
74a35b2b 24521: btst IMM (DBL_MANT_DIG-32),d0
0d64f74c
DE
2453 bne 2f | if set the number is normalized
2454| Normalize shifting left until bit #DBL_MANT_DIG-32 is set or the exponent
2455| is one (remember that a denormalized number corresponds to an
2456| exponent of -D_BIAS+1).
9425fb04 2457#ifndef __mcoldfire__
74a35b2b 2458 cmpw IMM (1),d4 | remember that the exponent is at least one
686cada4
ILT
2459#else
2460 cmpl IMM (1),d4 | remember that the exponent is at least one
2461#endif
0d64f74c
DE
2462 beq 2f | an exponent of one means denormalized
2463 addl d3,d3 | else shift and adjust the exponent
2464 addxl d2,d2 |
2465 addxl d1,d1 |
2466 addxl d0,d0 |
9425fb04 2467#ifndef __mcoldfire__
0d64f74c 2468 dbra d4,1b |
686cada4
ILT
2469#else
2470 subql IMM (1), d4
2471 bpl 1b
2472#endif
0d64f74c
DE
24732:
2474| Now round: we do it as follows: after the shifting we can write the
2475| fraction part as f + delta, where 1 < f < 2^25, and 0 <= delta <= 2.
2476| If delta < 1, do nothing. If delta > 1, add 1 to f.
2477| If delta == 1, we make sure the rounded number will be even (odd?)
2478| (after shifting).
74a35b2b 2479 btst IMM (0),d1 | is delta < 1?
0d64f74c
DE
2480 beq 2f | if so, do not do anything
2481 orl d2,d3 | is delta == 1?
2482 bne 1f | if so round to even
2483 movel d1,d3 |
74a35b2b
KR
2484 andl IMM (2),d3 | bit 1 is the last significant bit
2485 movel IMM (0),d2 |
0d64f74c
DE
2486 addl d3,d1 |
2487 addxl d2,d0 |
2488 bra 2f |
74a35b2b
KR
24891: movel IMM (1),d3 | else add 1
2490 movel IMM (0),d2 |
0d64f74c
DE
2491 addl d3,d1 |
2492 addxl d2,d0
2493| Shift right once (because we used bit #DBL_MANT_DIG-32!).
686cada4 24942:
9425fb04 2495#ifndef __mcoldfire__
686cada4 2496 lsrl IMM (1),d0
74a35b2b 2497 roxrl IMM (1),d1
686cada4
ILT
2498#else
2499 lsrl IMM (1),d1
2500 btst IMM (0),d0
2501 beq 10f
2502 bset IMM (31),d1
250310: lsrl IMM (1),d0
2504#endif
0d64f74c
DE
2505
2506| Now check again bit #DBL_MANT_DIG-32 (rounding could have produced a
2507| 'fraction overflow' ...).
74a35b2b 2508 btst IMM (DBL_MANT_DIG-32),d0
0d64f74c 2509 beq 1f
9425fb04 2510#ifndef __mcoldfire__
74a35b2b
KR
2511 lsrl IMM (1),d0
2512 roxrl IMM (1),d1
2513 addw IMM (1),d4
686cada4
ILT
2514#else
2515 lsrl IMM (1),d1
2516 btst IMM (0),d0
2517 beq 10f
2518 bset IMM (31),d1
251910: lsrl IMM (1),d0
2520 addl IMM (1),d4
2521#endif
0d64f74c
DE
25221:
2523| If bit #DBL_MANT_DIG-32-1 is clear we have a denormalized number, so we
2524| have to put the exponent to zero and return a denormalized number.
74a35b2b 2525 btst IMM (DBL_MANT_DIG-32-1),d0
0d64f74c
DE
2526 beq 1f
2527 jmp a0@
74a35b2b 25281: movel IMM (0),d4
0d64f74c
DE
2529 jmp a0@
2530
2531Lround$to$zero:
2532Lround$to$plus:
2533Lround$to$minus:
2534 jmp a0@
2535#endif /* L_double */
2536
2537#ifdef L_float
2538
2539 .globl SYM (_fpCCR)
2540 .globl $_exception_handler
2541
2542QUIET_NaN = 0xffffffff
2543SIGNL_NaN = 0x7f800001
2544INFINITY = 0x7f800000
2545
2546F_MAX_EXP = 0xff
2547F_BIAS = 126
2548FLT_MAX_EXP = F_MAX_EXP - F_BIAS
2549FLT_MIN_EXP = 1 - F_BIAS
2550FLT_MANT_DIG = 24
2551
2552INEXACT_RESULT = 0x0001
2553UNDERFLOW = 0x0002
2554OVERFLOW = 0x0004
2555DIVIDE_BY_ZERO = 0x0008
2556INVALID_OPERATION = 0x0010
2557
2558SINGLE_FLOAT = 1
2559
2560NOOP = 0
2561ADD = 1
2562MULTIPLY = 2
2563DIVIDE = 3
2564NEGATE = 4
2565COMPARE = 5
2566EXTENDSFDF = 6
2567TRUNCDFSF = 7
2568
2569UNKNOWN = -1
2570ROUND_TO_NEAREST = 0 | round result to nearest representable value
2571ROUND_TO_ZERO = 1 | round result towards zero
2572ROUND_TO_PLUS = 2 | round result towards plus infinity
2573ROUND_TO_MINUS = 3 | round result towards minus infinity
2574
2575| Entry points:
2576
2577 .globl SYM (__addsf3)
2578 .globl SYM (__subsf3)
2579 .globl SYM (__mulsf3)
2580 .globl SYM (__divsf3)
2581 .globl SYM (__negsf2)
2582 .globl SYM (__cmpsf2)
1a50d5e9 2583 .globl SYM (__cmpsf2_internal)
c1af059c 2584 .hidden SYM (__cmpsf2_internal)
0d64f74c
DE
2585
2586| These are common routines to return and signal exceptions.
2587
2588 .text
2589 .even
2590
2591Lf$den:
2592| Return and signal a denormalized number
2593 orl d7,d0
aa2192f8 2594 moveq IMM (INEXACT_RESULT+UNDERFLOW),d7
686cada4 2595 moveq IMM (SINGLE_FLOAT),d6
a2ef3db7 2596 PICJUMP $_exception_handler
0d64f74c
DE
2597
2598Lf$infty:
2599Lf$overflow:
2600| Return a properly signed INFINITY and set the exception flags
74a35b2b 2601 movel IMM (INFINITY),d0
0d64f74c 2602 orl d7,d0
aa2192f8 2603 moveq IMM (INEXACT_RESULT+OVERFLOW),d7
686cada4 2604 moveq IMM (SINGLE_FLOAT),d6
a2ef3db7 2605 PICJUMP $_exception_handler
0d64f74c
DE
2606
2607Lf$underflow:
2608| Return 0 and set the exception flags
aa2192f8
NS
2609 moveq IMM (0),d0
2610 moveq IMM (INEXACT_RESULT+UNDERFLOW),d7
686cada4 2611 moveq IMM (SINGLE_FLOAT),d6
a2ef3db7 2612 PICJUMP $_exception_handler
0d64f74c
DE
2613
2614Lf$inop:
2615| Return a quiet NaN and set the exception flags
74a35b2b 2616 movel IMM (QUIET_NaN),d0
aa2192f8 2617 moveq IMM (INEXACT_RESULT+INVALID_OPERATION),d7
686cada4 2618 moveq IMM (SINGLE_FLOAT),d6
a2ef3db7 2619 PICJUMP $_exception_handler
0d64f74c
DE
2620
2621Lf$div$0:
2622| Return a properly signed INFINITY and set the exception flags
74a35b2b 2623 movel IMM (INFINITY),d0
0d64f74c 2624 orl d7,d0
aa2192f8 2625 moveq IMM (INEXACT_RESULT+DIVIDE_BY_ZERO),d7
686cada4 2626 moveq IMM (SINGLE_FLOAT),d6
a2ef3db7 2627 PICJUMP $_exception_handler
0d64f74c
DE
2628
2629|=============================================================================
2630|=============================================================================
2631| single precision routines
2632|=============================================================================
2633|=============================================================================
2634
2635| A single precision floating point number (float) has the format:
2636|
2637| struct _float {
2638| unsigned int sign : 1; /* sign bit */
2639| unsigned int exponent : 8; /* exponent, shifted by 126 */
2640| unsigned int fraction : 23; /* fraction */
2641| } float;
2642|
2643| Thus sizeof(float) = 4 (32 bits).
2644|
2645| All the routines are callable from C programs, and return the result
2646| in the single register d0. They also preserve all registers except
2647| d0-d1 and a0-a1.
2648
2649|=============================================================================
2650| __subsf3
2651|=============================================================================
2652
2653| float __subsf3(float, float);
2786eb8d 2654 FUNC(__subsf3)
0d64f74c 2655SYM (__subsf3):
74a35b2b 2656 bchg IMM (31),sp@(8) | change sign of second operand
0d64f74c
DE
2657 | and fall through
2658|=============================================================================
2659| __addsf3
2660|=============================================================================
2661
2662| float __addsf3(float, float);
2786eb8d 2663 FUNC(__addsf3)
0d64f74c 2664SYM (__addsf3):
9425fb04 2665#ifndef __mcoldfire__
74a35b2b 2666 link a6,IMM (0) | everything will be done in registers
0d64f74c 2667 moveml d2-d7,sp@- | save all data registers but d0-d1
e82673c4
RK
2668#else
2669 link a6,IMM (-24)
2670 moveml d2-d7,sp@
2671#endif
0d64f74c
DE
2672 movel a6@(8),d0 | get first operand
2673 movel a6@(12),d1 | get second operand
75a75b88 2674 movel d0,a0 | get d0's sign bit '
0d64f74c
DE
2675 addl d0,d0 | check and clear sign bit of a
2676 beq Laddsf$b | if zero return second operand
75a75b88 2677 movel d1,a1 | save b's sign bit '
0d64f74c
DE
2678 addl d1,d1 | get rid of sign bit
2679 beq Laddsf$a | if zero return first operand
2680
0d64f74c
DE
2681| Get the exponents and check for denormalized and/or infinity.
2682
74a35b2b
KR
2683 movel IMM (0x00ffffff),d4 | mask to get fraction
2684 movel IMM (0x01000000),d5 | mask to put hidden bit back
0d64f74c
DE
2685
2686 movel d0,d6 | save a to get exponent
2687 andl d4,d0 | get fraction in d0
2688 notl d4 | make d4 into a mask for the exponent
2689 andl d4,d6 | get exponent in d6
2690 beq Laddsf$a$den | branch if a is denormalized
2691 cmpl d4,d6 | check for INFINITY or NaN
2692 beq Laddsf$nf
2693 swap d6 | put exponent into first word
2694 orl d5,d0 | and put hidden bit back
2695Laddsf$1:
2696| Now we have a's exponent in d6 (second byte) and the mantissa in d0. '
2697 movel d1,d7 | get exponent in d7
2698 andl d4,d7 |
2699 beq Laddsf$b$den | branch if b is denormalized
2700 cmpl d4,d7 | check for INFINITY or NaN
2701 beq Laddsf$nf
2702 swap d7 | put exponent into first word
2703 notl d4 | make d4 into a mask for the fraction
2704 andl d4,d1 | get fraction in d1
2705 orl d5,d1 | and put hidden bit back
2706Laddsf$2:
2707| Now we have b's exponent in d7 (second byte) and the mantissa in d1. '
2708
2709| Note that the hidden bit corresponds to bit #FLT_MANT_DIG-1, and we
2710| shifted right once, so bit #FLT_MANT_DIG is set (so we have one extra
2711| bit).
2712
2713 movel d1,d2 | move b to d2, since we want to use
2714 | two registers to do the sum
74a35b2b 2715 movel IMM (0),d1 | and clear the new ones
0d64f74c
DE
2716 movel d1,d3 |
2717
2718| Here we shift the numbers in registers d0 and d1 so the exponents are the
2719| same, and put the largest exponent in d6. Note that we are using two
2720| registers for each number (see the discussion by D. Knuth in "Seminumerical
2721| Algorithms").
9425fb04 2722#ifndef __mcoldfire__
0d64f74c 2723 cmpw d6,d7 | compare exponents
686cada4
ILT
2724#else
2725 cmpl d6,d7 | compare exponents
2726#endif
0d64f74c
DE
2727 beq Laddsf$3 | if equal don't shift '
2728 bhi 5f | branch if second exponent largest
27291:
2730 subl d6,d7 | keep the largest exponent
2731 negl d7
9425fb04 2732#ifndef __mcoldfire__
74a35b2b 2733 lsrw IMM (8),d7 | put difference in lower byte
686cada4
ILT
2734#else
2735 lsrl IMM (8),d7 | put difference in lower byte
2736#endif
0d64f74c 2737| if difference is too large we don't shift (actually, we can just exit) '
9425fb04 2738#ifndef __mcoldfire__
74a35b2b 2739 cmpw IMM (FLT_MANT_DIG+2),d7
686cada4
ILT
2740#else
2741 cmpl IMM (FLT_MANT_DIG+2),d7
2742#endif
0d64f74c 2743 bge Laddsf$b$small
9425fb04 2744#ifndef __mcoldfire__
74a35b2b 2745 cmpw IMM (16),d7 | if difference >= 16 swap
686cada4
ILT
2746#else
2747 cmpl IMM (16),d7 | if difference >= 16 swap
2748#endif
0d64f74c
DE
2749 bge 4f
27502:
9425fb04 2751#ifndef __mcoldfire__
74a35b2b 2752 subw IMM (1),d7
686cada4
ILT
2753#else
2754 subql IMM (1), d7
2755#endif
27563:
9425fb04 2757#ifndef __mcoldfire__
686cada4 2758 lsrl IMM (1),d2 | shift right second operand
74a35b2b 2759 roxrl IMM (1),d3
0d64f74c 2760 dbra d7,3b
686cada4
ILT
2761#else
2762 lsrl IMM (1),d3
2763 btst IMM (0),d2
2764 beq 10f
2765 bset IMM (31),d3
276610: lsrl IMM (1),d2
2767 subql IMM (1), d7
2768 bpl 3b
2769#endif
0d64f74c
DE
2770 bra Laddsf$3
27714:
2772 movew d2,d3
2773 swap d3
2774 movew d3,d2
2775 swap d2
9425fb04 2776#ifndef __mcoldfire__
74a35b2b 2777 subw IMM (16),d7
686cada4
ILT
2778#else
2779 subl IMM (16),d7
2780#endif
2655599b
JW
2781 bne 2b | if still more bits, go back to normal case
2782 bra Laddsf$3
0d64f74c 27835:
9425fb04 2784#ifndef __mcoldfire__
0d64f74c 2785 exg d6,d7 | exchange the exponents
686cada4
ILT
2786#else
2787 eorl d6,d7
2788 eorl d7,d6
2789 eorl d6,d7
2790#endif
0d64f74c
DE
2791 subl d6,d7 | keep the largest exponent
2792 negl d7 |
9425fb04 2793#ifndef __mcoldfire__
74a35b2b 2794 lsrw IMM (8),d7 | put difference in lower byte
686cada4
ILT
2795#else
2796 lsrl IMM (8),d7 | put difference in lower byte
2797#endif
0d64f74c 2798| if difference is too large we don't shift (and exit!) '
9425fb04 2799#ifndef __mcoldfire__
74a35b2b 2800 cmpw IMM (FLT_MANT_DIG+2),d7
686cada4
ILT
2801#else
2802 cmpl IMM (FLT_MANT_DIG+2),d7
2803#endif
0d64f74c 2804 bge Laddsf$a$small
9425fb04 2805#ifndef __mcoldfire__
74a35b2b 2806 cmpw IMM (16),d7 | if difference >= 16 swap
686cada4
ILT
2807#else
2808 cmpl IMM (16),d7 | if difference >= 16 swap
2809#endif
0d64f74c
DE
2810 bge 8f
28116:
9425fb04 2812#ifndef __mcoldfire__
74a35b2b 2813 subw IMM (1),d7
686cada4
ILT
2814#else
2815 subl IMM (1),d7
2816#endif
28177:
9425fb04 2818#ifndef __mcoldfire__
686cada4 2819 lsrl IMM (1),d0 | shift right first operand
74a35b2b 2820 roxrl IMM (1),d1
0d64f74c 2821 dbra d7,7b
686cada4
ILT
2822#else
2823 lsrl IMM (1),d1
2824 btst IMM (0),d0
2825 beq 10f
2826 bset IMM (31),d1
282710: lsrl IMM (1),d0
2828 subql IMM (1),d7
2829 bpl 7b
2830#endif
0d64f74c
DE
2831 bra Laddsf$3
28328:
2833 movew d0,d1
2834 swap d1
2835 movew d1,d0
2836 swap d0
9425fb04 2837#ifndef __mcoldfire__
74a35b2b 2838 subw IMM (16),d7
686cada4
ILT
2839#else
2840 subl IMM (16),d7
2841#endif
2655599b
JW
2842 bne 6b | if still more bits, go back to normal case
2843 | otherwise we fall through
0d64f74c
DE
2844
2845| Now we have a in d0-d1, b in d2-d3, and the largest exponent in d6 (the
2846| signs are stored in a0 and a1).
2847
2848Laddsf$3:
ddd5a7c1 2849| Here we have to decide whether to add or subtract the numbers
9425fb04 2850#ifndef __mcoldfire__
0d64f74c
DE
2851 exg d6,a0 | get signs back
2852 exg d7,a1 | and save the exponents
686cada4
ILT
2853#else
2854 movel d6,d4
2855 movel a0,d6
1688d6d2 2856 movel d4,a0
686cada4 2857 movel d7,d4
1688d6d2 2858 movel a1,d7
686cada4
ILT
2859 movel d4,a1
2860#endif
0d64f74c
DE
2861 eorl d6,d7 | combine sign bits
2862 bmi Lsubsf$0 | if negative a and b have opposite
ddd5a7c1 2863 | sign so we actually subtract the
0d64f74c
DE
2864 | numbers
2865
2866| Here we have both positive or both negative
9425fb04 2867#ifndef __mcoldfire__
0d64f74c 2868 exg d6,a0 | now we have the exponent in d6
686cada4
ILT
2869#else
2870 movel d6,d4
2871 movel a0,d6
2872 movel d4,a0
2873#endif
0d64f74c 2874 movel a0,d7 | and sign in d7
74a35b2b 2875 andl IMM (0x80000000),d7
0d64f74c
DE
2876| Here we do the addition.
2877 addl d3,d1
2878 addxl d2,d0
2879| Note: now we have d2, d3, d4 and d5 to play with!
2880
2881| Put the exponent, in the first byte, in d2, to use the "standard" rounding
2882| routines:
2883 movel d6,d2
9425fb04 2884#ifndef __mcoldfire__
74a35b2b 2885 lsrw IMM (8),d2
686cada4
ILT
2886#else
2887 lsrl IMM (8),d2
2888#endif
0d64f74c
DE
2889
2890| Before rounding normalize so bit #FLT_MANT_DIG is set (we will consider
2891| the case of denormalized numbers in the rounding routine itself).
ddd5a7c1 2892| As in the addition (not in the subtraction!) we could have set
0d64f74c 2893| one more bit we check this:
74a35b2b 2894 btst IMM (FLT_MANT_DIG+1),d0
0d64f74c 2895 beq 1f
9425fb04 2896#ifndef __mcoldfire__
74a35b2b
KR
2897 lsrl IMM (1),d0
2898 roxrl IMM (1),d1
686cada4
ILT
2899#else
2900 lsrl IMM (1),d1
2901 btst IMM (0),d0
2902 beq 10f
2903 bset IMM (31),d1
290410: lsrl IMM (1),d0
2905#endif
74a35b2b 2906 addl IMM (1),d2
0d64f74c 29071:
a2ef3db7
BI
2908 lea pc@(Laddsf$4),a0 | to return from rounding routine
2909 PICLEA SYM (_fpCCR),a1 | check the rounding mode
9425fb04 2910#ifdef __mcoldfire__
686cada4
ILT
2911 clrl d6
2912#endif
0d64f74c
DE
2913 movew a1@(6),d6 | rounding mode in d6
2914 beq Lround$to$nearest
9425fb04 2915#ifndef __mcoldfire__
74a35b2b 2916 cmpw IMM (ROUND_TO_PLUS),d6
686cada4
ILT
2917#else
2918 cmpl IMM (ROUND_TO_PLUS),d6
2919#endif
0d64f74c
DE
2920 bhi Lround$to$minus
2921 blt Lround$to$zero
2922 bra Lround$to$plus
2923Laddsf$4:
2924| Put back the exponent, but check for overflow.
9425fb04 2925#ifndef __mcoldfire__
74a35b2b 2926 cmpw IMM (0xff),d2
686cada4
ILT
2927#else
2928 cmpl IMM (0xff),d2
2929#endif
0d64f74c 2930 bhi 1f
74a35b2b 2931 bclr IMM (FLT_MANT_DIG-1),d0
9425fb04 2932#ifndef __mcoldfire__
74a35b2b 2933 lslw IMM (7),d2
686cada4
ILT
2934#else
2935 lsll IMM (7),d2
2936#endif
0d64f74c
DE
2937 swap d2
2938 orl d2,d0
2939 bra Laddsf$ret
29401:
aa2192f8 2941 moveq IMM (ADD),d5
0d64f74c
DE
2942 bra Lf$overflow
2943
2944Lsubsf$0:
2945| We are here if a > 0 and b < 0 (sign bits cleared).
ddd5a7c1 2946| Here we do the subtraction.
0d64f74c 2947 movel d6,d7 | put sign in d7
74a35b2b 2948 andl IMM (0x80000000),d7
0d64f74c
DE
2949
2950 subl d3,d1 | result in d0-d1
2951 subxl d2,d0 |
2952 beq Laddsf$ret | if zero just exit
2953 bpl 1f | if positive skip the following
74a35b2b 2954 bchg IMM (31),d7 | change sign bit in d7
0d64f74c
DE
2955 negl d1
2956 negxl d0
29571:
9425fb04 2958#ifndef __mcoldfire__
0d64f74c 2959 exg d2,a0 | now we have the exponent in d2
74a35b2b 2960 lsrw IMM (8),d2 | put it in the first byte
686cada4
ILT
2961#else
2962 movel d2,d4
2963 movel a0,d2
2964 movel d4,a0
2965 lsrl IMM (8),d2 | put it in the first byte
2966#endif
0d64f74c
DE
2967
2968| Now d0-d1 is positive and the sign bit is in d7.
2969
ddd5a7c1 2970| Note that we do not have to normalize, since in the subtraction bit
0d64f74c
DE
2971| #FLT_MANT_DIG+1 is never set, and denormalized numbers are handled by
2972| the rounding routines themselves.
a2ef3db7
BI
2973 lea pc@(Lsubsf$1),a0 | to return from rounding routine
2974 PICLEA SYM (_fpCCR),a1 | check the rounding mode
9425fb04 2975#ifdef __mcoldfire__
686cada4
ILT
2976 clrl d6
2977#endif
0d64f74c
DE
2978 movew a1@(6),d6 | rounding mode in d6
2979 beq Lround$to$nearest
9425fb04 2980#ifndef __mcoldfire__
74a35b2b 2981 cmpw IMM (ROUND_TO_PLUS),d6
686cada4
ILT
2982#else
2983 cmpl IMM (ROUND_TO_PLUS),d6
2984#endif
0d64f74c
DE
2985 bhi Lround$to$minus
2986 blt Lround$to$zero
2987 bra Lround$to$plus
2988Lsubsf$1:
2989| Put back the exponent (we can't have overflow!). '
74a35b2b 2990 bclr IMM (FLT_MANT_DIG-1),d0
9425fb04 2991#ifndef __mcoldfire__
74a35b2b 2992 lslw IMM (7),d2
686cada4
ILT
2993#else
2994 lsll IMM (7),d2
2995#endif
0d64f74c
DE
2996 swap d2
2997 orl d2,d0
2998 bra Laddsf$ret
2999
3000| If one of the numbers was too small (difference of exponents >=
3001| FLT_MANT_DIG+2) we return the other (and now we don't have to '
3002| check for finiteness or zero).
3003Laddsf$a$small:
3004 movel a6@(12),d0
a2ef3db7 3005 PICLEA SYM (_fpCCR),a0
74a35b2b 3006 movew IMM (0),a0@
9425fb04 3007#ifndef __mcoldfire__
0d64f74c 3008 moveml sp@+,d2-d7 | restore data registers
e82673c4
RK
3009#else
3010 moveml sp@,d2-d7
3011 | XXX if frame pointer is ever removed, stack pointer must
3012 | be adjusted here.
3013#endif
0d64f74c
DE
3014 unlk a6 | and return
3015 rts
3016
3017Laddsf$b$small:
3018 movel a6@(8),d0
a2ef3db7 3019 PICLEA SYM (_fpCCR),a0
74a35b2b 3020 movew IMM (0),a0@
9425fb04 3021#ifndef __mcoldfire__
0d64f74c 3022 moveml sp@+,d2-d7 | restore data registers
e82673c4
RK
3023#else
3024 moveml sp@,d2-d7
3025 | XXX if frame pointer is ever removed, stack pointer must
3026 | be adjusted here.
3027#endif
0d64f74c
DE
3028 unlk a6 | and return
3029 rts
3030
3031| If the numbers are denormalized remember to put exponent equal to 1.
3032
3033Laddsf$a$den:
3034 movel d5,d6 | d5 contains 0x01000000
3035 swap d6
3036 bra Laddsf$1
3037
3038Laddsf$b$den:
3039 movel d5,d7
3040 swap d7
3041 notl d4 | make d4 into a mask for the fraction
3042 | (this was not executed after the jump)
3043 bra Laddsf$2
3044
3045| The rest is mainly code for the different results which can be
3046| returned (checking always for +/-INFINITY and NaN).
3047
3048Laddsf$b:
3049| Return b (if a is zero).
3050 movel a6@(12),d0
75a75b88
PB
3051 cmpl IMM (0x80000000),d0 | Check if b is -0
3052 bne 1f
3053 movel a0,d7
3054 andl IMM (0x80000000),d7 | Use the sign of a
3055 clrl d0
3056 bra Laddsf$ret
0d64f74c
DE
3057Laddsf$a:
3058| Return a (if b is zero).
3059 movel a6@(8),d0
30601:
aa2192f8 3061 moveq IMM (ADD),d5
0d64f74c
DE
3062| We have to check for NaN and +/-infty.
3063 movel d0,d7
74a35b2b
KR
3064 andl IMM (0x80000000),d7 | put sign in d7
3065 bclr IMM (31),d0 | clear sign
3066 cmpl IMM (INFINITY),d0 | check for infty or NaN
0d64f74c
DE
3067 bge 2f
3068 movel d0,d0 | check for zero (we do this because we don't '
3069 bne Laddsf$ret | want to return -0 by mistake
74a35b2b 3070 bclr IMM (31),d7 | if zero be sure to clear sign
0d64f74c
DE
3071 bra Laddsf$ret | if everything OK just return
30722:
3073| The value to be returned is either +/-infty or NaN
74a35b2b
KR
3074 andl IMM (0x007fffff),d0 | check for NaN
3075 bne Lf$inop | if mantissa not zero is NaN
0d64f74c
DE
3076 bra Lf$infty
3077
3078Laddsf$ret:
3079| Normal exit (a and b nonzero, result is not NaN nor +/-infty).
3080| We have to clear the exception flags (just the exception type).
a2ef3db7 3081 PICLEA SYM (_fpCCR),a0
74a35b2b 3082 movew IMM (0),a0@
0d64f74c 3083 orl d7,d0 | put sign bit
9425fb04 3084#ifndef __mcoldfire__
0d64f74c 3085 moveml sp@+,d2-d7 | restore data registers
e82673c4
RK
3086#else
3087 moveml sp@,d2-d7
3088 | XXX if frame pointer is ever removed, stack pointer must
3089 | be adjusted here.
3090#endif
0d64f74c
DE
3091 unlk a6 | and return
3092 rts
3093
3094Laddsf$ret$den:
3095| Return a denormalized number (for addition we don't signal underflow) '
74a35b2b 3096 lsrl IMM (1),d0 | remember to shift right back once
0d64f74c
DE
3097 bra Laddsf$ret | and return
3098
3099| Note: when adding two floats of the same sign if either one is
3100| NaN we return NaN without regard to whether the other is finite or
ddd5a7c1 3101| not. When subtracting them (i.e., when adding two numbers of
0d64f74c
DE
3102| opposite signs) things are more complicated: if both are INFINITY
3103| we return NaN, if only one is INFINITY and the other is NaN we return
3104| NaN, but if it is finite we return INFINITY with the corresponding sign.
3105
3106Laddsf$nf:
aa2192f8 3107 moveq IMM (ADD),d5
0d64f74c
DE
3108| This could be faster but it is not worth the effort, since it is not
3109| executed very often. We sacrifice speed for clarity here.
3110 movel a6@(8),d0 | get the numbers back (remember that we
3111 movel a6@(12),d1 | did some processing already)
74a35b2b 3112 movel IMM (INFINITY),d4 | useful constant (INFINITY)
0d64f74c
DE
3113 movel d0,d2 | save sign bits
3114 movel d1,d3
74a35b2b
KR
3115 bclr IMM (31),d0 | clear sign bits
3116 bclr IMM (31),d1
0d64f74c
DE
3117| We know that one of them is either NaN of +/-INFINITY
3118| Check for NaN (if either one is NaN return NaN)
3119 cmpl d4,d0 | check first a (d0)
3120 bhi Lf$inop
3121 cmpl d4,d1 | check now b (d1)
3122 bhi Lf$inop
3123| Now comes the check for +/-INFINITY. We know that both are (maybe not
3124| finite) numbers, but we have to check if both are infinite whether we
ddd5a7c1 3125| are adding or subtracting them.
0d64f74c
DE
3126 eorl d3,d2 | to check sign bits
3127 bmi 1f
3128 movel d0,d7
74a35b2b 3129 andl IMM (0x80000000),d7 | get (common) sign bit
0d64f74c
DE
3130 bra Lf$infty
31311:
3132| We know one (or both) are infinite, so we test for equality between the
3133| two numbers (if they are equal they have to be infinite both, so we
3134| return NaN).
3135 cmpl d1,d0 | are both infinite?
3136 beq Lf$inop | if so return NaN
3137
3138 movel d0,d7
74a35b2b 3139 andl IMM (0x80000000),d7 | get a's sign bit '
0d64f74c
DE
3140 cmpl d4,d0 | test now for infinity
3141 beq Lf$infty | if a is INFINITY return with this sign
74a35b2b 3142 bchg IMM (31),d7 | else we know b is INFINITY and has
0d64f74c
DE
3143 bra Lf$infty | the opposite sign
3144
3145|=============================================================================
3146| __mulsf3
3147|=============================================================================
3148
3149| float __mulsf3(float, float);
2786eb8d 3150 FUNC(__mulsf3)
0d64f74c 3151SYM (__mulsf3):
9425fb04 3152#ifndef __mcoldfire__
74a35b2b 3153 link a6,IMM (0)
0d64f74c 3154 moveml d2-d7,sp@-
e82673c4
RK
3155#else
3156 link a6,IMM (-24)
3157 moveml d2-d7,sp@
3158#endif
0d64f74c
DE
3159 movel a6@(8),d0 | get a into d0
3160 movel a6@(12),d1 | and b into d1
3161 movel d0,d7 | d7 will hold the sign of the product
3162 eorl d1,d7 |
74a35b2b
KR
3163 andl IMM (0x80000000),d7
3164 movel IMM (INFINITY),d6 | useful constant (+INFINITY)
3165 movel d6,d5 | another (mask for fraction)
3166 notl d5 |
3167 movel IMM (0x00800000),d4 | this is to put hidden bit back
3168 bclr IMM (31),d0 | get rid of a's sign bit '
3169 movel d0,d2 |
3170 beq Lmulsf$a$0 | branch if a is zero
3171 bclr IMM (31),d1 | get rid of b's sign bit '
0d64f74c
DE
3172 movel d1,d3 |
3173 beq Lmulsf$b$0 | branch if b is zero
3174 cmpl d6,d0 | is a big?
3175 bhi Lmulsf$inop | if a is NaN return NaN
3176 beq Lmulsf$inf | if a is INFINITY we have to check b
3177 cmpl d6,d1 | now compare b with INFINITY
3178 bhi Lmulsf$inop | is b NaN?
3179 beq Lmulsf$overflow | is b INFINITY?
3180| Here we have both numbers finite and nonzero (and with no sign bit).
3181| Now we get the exponents into d2 and d3.
3182 andl d6,d2 | and isolate exponent in d2
3183 beq Lmulsf$a$den | if exponent is zero we have a denormalized
3184 andl d5,d0 | and isolate fraction
3185 orl d4,d0 | and put hidden bit back
3186 swap d2 | I like exponents in the first byte
9425fb04 3187#ifndef __mcoldfire__
74a35b2b 3188 lsrw IMM (7),d2 |
686cada4
ILT
3189#else
3190 lsrl IMM (7),d2 |
3191#endif
0d64f74c
DE
3192Lmulsf$1: | number
3193 andl d6,d3 |
3194 beq Lmulsf$b$den |
3195 andl d5,d1 |
3196 orl d4,d1 |
3197 swap d3 |
9425fb04 3198#ifndef __mcoldfire__
74a35b2b 3199 lsrw IMM (7),d3 |
686cada4
ILT
3200#else
3201 lsrl IMM (7),d3 |
3202#endif
0d64f74c 3203Lmulsf$2: |
9425fb04 3204#ifndef __mcoldfire__
0d64f74c 3205 addw d3,d2 | add exponents
ddd5a7c1 3206 subw IMM (F_BIAS+1),d2 | and subtract bias (plus one)
686cada4
ILT
3207#else
3208 addl d3,d2 | add exponents
3209 subl IMM (F_BIAS+1),d2 | and subtract bias (plus one)
3210#endif
0d64f74c
DE
3211
3212| We are now ready to do the multiplication. The situation is as follows:
3213| both a and b have bit FLT_MANT_DIG-1 set (even if they were
3214| denormalized to start with!), which means that in the product
3215| bit 2*(FLT_MANT_DIG-1) (that is, bit 2*FLT_MANT_DIG-2-32 of the
3216| high long) is set.
3217
3218| To do the multiplication let us move the number a little bit around ...
3219 movel d1,d6 | second operand in d6
3220 movel d0,d5 | first operand in d4-d5
74a35b2b 3221 movel IMM (0),d4
0d64f74c
DE
3222 movel d4,d1 | the sums will go in d0-d1
3223 movel d4,d0
3224
3225| now bit FLT_MANT_DIG-1 becomes bit 31:
74a35b2b 3226 lsll IMM (31-FLT_MANT_DIG+1),d6
0d64f74c
DE
3227
3228| Start the loop (we loop #FLT_MANT_DIG times):
aa2192f8 3229 moveq IMM (FLT_MANT_DIG-1),d3
0d64f74c
DE
32301: addl d1,d1 | shift sum
3231 addxl d0,d0
74a35b2b 3232 lsll IMM (1),d6 | get bit bn
0d64f74c
DE
3233 bcc 2f | if not set skip sum
3234 addl d5,d1 | add a
3235 addxl d4,d0
686cada4 32362:
9425fb04 3237#ifndef __mcoldfire__
686cada4
ILT
3238 dbf d3,1b | loop back
3239#else
3240 subql IMM (1),d3
3241 bpl 1b
3242#endif
0d64f74c
DE
3243
3244| Now we have the product in d0-d1, with bit (FLT_MANT_DIG - 1) + FLT_MANT_DIG
3245| (mod 32) of d0 set. The first thing to do now is to normalize it so bit
3246| FLT_MANT_DIG is set (to do the rounding).
9425fb04 3247#ifndef __mcoldfire__
74a35b2b 3248 rorl IMM (6),d1
0d64f74c
DE
3249 swap d1
3250 movew d1,d3
74a35b2b
KR
3251 andw IMM (0x03ff),d3
3252 andw IMM (0xfd00),d1
686cada4
ILT
3253#else
3254 movel d1,d3
3255 lsll IMM (8),d1
3256 addl d1,d1
3257 addl d1,d1
3258 moveq IMM (22),d5
3259 lsrl d5,d3
3260 orl d3,d1
3261 andl IMM (0xfffffd00),d1
3262#endif
74a35b2b 3263 lsll IMM (8),d0
0d64f74c
DE
3264 addl d0,d0
3265 addl d0,d0
9425fb04 3266#ifndef __mcoldfire__
0d64f74c 3267 orw d3,d0
686cada4
ILT
3268#else
3269 orl d3,d0
3270#endif
0d64f74c 3271
aa2192f8 3272 moveq IMM (MULTIPLY),d5
0d64f74c 3273
74a35b2b 3274 btst IMM (FLT_MANT_DIG+1),d0
0d64f74c 3275 beq Lround$exit
9425fb04 3276#ifndef __mcoldfire__
74a35b2b
KR
3277 lsrl IMM (1),d0
3278 roxrl IMM (1),d1
3279 addw IMM (1),d2
686cada4
ILT
3280#else
3281 lsrl IMM (1),d1
3282 btst IMM (0),d0
3283 beq 10f
3284 bset IMM (31),d1
328510: lsrl IMM (1),d0
3286 addql IMM (1),d2
3287#endif
0d64f74c
DE
3288 bra Lround$exit
3289
3290Lmulsf$inop:
aa2192f8 3291 moveq IMM (MULTIPLY),d5
0d64f74c
DE
3292 bra Lf$inop
3293
3294Lmulsf$overflow:
aa2192f8 3295 moveq IMM (MULTIPLY),d5
0d64f74c
DE
3296 bra Lf$overflow
3297
3298Lmulsf$inf:
aa2192f8 3299 moveq IMM (MULTIPLY),d5
0d64f74c
DE
3300| If either is NaN return NaN; else both are (maybe infinite) numbers, so
3301| return INFINITY with the correct sign (which is in d7).
3302 cmpl d6,d1 | is b NaN?
3303 bhi Lf$inop | if so return NaN
3304 bra Lf$overflow | else return +/-INFINITY
3305
3306| If either number is zero return zero, unless the other is +/-INFINITY,
3307| or NaN, in which case we return NaN.
3308Lmulsf$b$0:
3309| Here d1 (==b) is zero.
0d64f74c
DE
3310 movel a6@(8),d1 | get a again to check for non-finiteness
3311 bra 1f
3312Lmulsf$a$0:
3313 movel a6@(12),d1 | get b again to check for non-finiteness
74a35b2b
KR
33141: bclr IMM (31),d1 | clear sign bit
3315 cmpl IMM (INFINITY),d1 | and check for a large exponent
0d64f74c 3316 bge Lf$inop | if b is +/-INFINITY or NaN return NaN
d55f9d23
NS
3317 movel d7,d0 | else return signed zero
3318 PICLEA SYM (_fpCCR),a0 |
74a35b2b 3319 movew IMM (0),a0@ |
9425fb04 3320#ifndef __mcoldfire__
0d64f74c 3321 moveml sp@+,d2-d7 |
e82673c4
RK
3322#else
3323 moveml sp@,d2-d7
3324 | XXX if frame pointer is ever removed, stack pointer must
3325 | be adjusted here.
3326#endif
0d64f74c
DE
3327 unlk a6 |
3328 rts |
3329
3330| If a number is denormalized we put an exponent of 1 but do not put the
3331| hidden bit back into the fraction; instead we shift left until bit 23
3332| (the hidden bit) is set, adjusting the exponent accordingly. We do this
3333| to ensure that the product of the fractions is close to 1.
3334Lmulsf$a$den:
74a35b2b 3335 movel IMM (1),d2
0d64f74c
DE
3336 andl d5,d0
33371: addl d0,d0 | shift a left (until bit 23 is set)
9425fb04 3338#ifndef __mcoldfire__
74a35b2b 3339 subw IMM (1),d2 | and adjust exponent
686cada4
ILT
3340#else
3341 subql IMM (1),d2 | and adjust exponent
3342#endif
74a35b2b 3343 btst IMM (FLT_MANT_DIG-1),d0
0d64f74c
DE
3344 bne Lmulsf$1 |
3345 bra 1b | else loop back
3346
3347Lmulsf$b$den:
74a35b2b 3348 movel IMM (1),d3
0d64f74c
DE
3349 andl d5,d1
33501: addl d1,d1 | shift b left until bit 23 is set
9425fb04 3351#ifndef __mcoldfire__
74a35b2b 3352 subw IMM (1),d3 | and adjust exponent
686cada4 3353#else
aa2192f8 3354 subql IMM (1),d3 | and adjust exponent
686cada4 3355#endif
74a35b2b 3356 btst IMM (FLT_MANT_DIG-1),d1
0d64f74c
DE
3357 bne Lmulsf$2 |
3358 bra 1b | else loop back
3359
3360|=============================================================================
3361| __divsf3
3362|=============================================================================
3363
3364| float __divsf3(float, float);
2786eb8d 3365 FUNC(__divsf3)
0d64f74c 3366SYM (__divsf3):
9425fb04 3367#ifndef __mcoldfire__
74a35b2b 3368 link a6,IMM (0)
0d64f74c 3369 moveml d2-d7,sp@-
e82673c4
RK
3370#else
3371 link a6,IMM (-24)
3372 moveml d2-d7,sp@
3373#endif
74a35b2b
KR
3374 movel a6@(8),d0 | get a into d0
3375 movel a6@(12),d1 | and b into d1
3376 movel d0,d7 | d7 will hold the sign of the result
3377 eorl d1,d7 |
3378 andl IMM (0x80000000),d7 |
3379 movel IMM (INFINITY),d6 | useful constant (+INFINITY)
3380 movel d6,d5 | another (mask for fraction)
3381 notl d5 |
3382 movel IMM (0x00800000),d4 | this is to put hidden bit back
3383 bclr IMM (31),d0 | get rid of a's sign bit '
3384 movel d0,d2 |
3385 beq Ldivsf$a$0 | branch if a is zero
3386 bclr IMM (31),d1 | get rid of b's sign bit '
3387 movel d1,d3 |
3388 beq Ldivsf$b$0 | branch if b is zero
3389 cmpl d6,d0 | is a big?
3390 bhi Ldivsf$inop | if a is NaN return NaN
ddd5a7c1 3391 beq Ldivsf$inf | if a is INFINITY we have to check b
74a35b2b
KR
3392 cmpl d6,d1 | now compare b with INFINITY
3393 bhi Ldivsf$inop | if b is NaN return NaN
0d64f74c
DE
3394 beq Ldivsf$underflow
3395| Here we have both numbers finite and nonzero (and with no sign bit).
3396| Now we get the exponents into d2 and d3 and normalize the numbers to
3397| ensure that the ratio of the fractions is close to 1. We do this by
3398| making sure that bit #FLT_MANT_DIG-1 (hidden bit) is set.
3399 andl d6,d2 | and isolate exponent in d2
3400 beq Ldivsf$a$den | if exponent is zero we have a denormalized
3401 andl d5,d0 | and isolate fraction
3402 orl d4,d0 | and put hidden bit back
3403 swap d2 | I like exponents in the first byte
9425fb04 3404#ifndef __mcoldfire__
74a35b2b 3405 lsrw IMM (7),d2 |
686cada4
ILT
3406#else
3407 lsrl IMM (7),d2 |
3408#endif
0d64f74c
DE
3409Ldivsf$1: |
3410 andl d6,d3 |
3411 beq Ldivsf$b$den |
3412 andl d5,d1 |
3413 orl d4,d1 |
3414 swap d3 |
9425fb04 3415#ifndef __mcoldfire__
74a35b2b 3416 lsrw IMM (7),d3 |
686cada4
ILT
3417#else
3418 lsrl IMM (7),d3 |
3419#endif
0d64f74c 3420Ldivsf$2: |
9425fb04 3421#ifndef __mcoldfire__
ddd5a7c1 3422 subw d3,d2 | subtract exponents
74a35b2b 3423 addw IMM (F_BIAS),d2 | and add bias
686cada4
ILT
3424#else
3425 subl d3,d2 | subtract exponents
3426 addl IMM (F_BIAS),d2 | and add bias
3427#endif
0d64f74c
DE
3428
3429| We are now ready to do the division. We have prepared things in such a way
3430| that the ratio of the fractions will be less than 2 but greater than 1/2.
3431| At this point the registers in use are:
3432| d0 holds a (first operand, bit FLT_MANT_DIG=0, bit FLT_MANT_DIG-1=1)
3433| d1 holds b (second operand, bit FLT_MANT_DIG=1)
3434| d2 holds the difference of the exponents, corrected by the bias
3435| d7 holds the sign of the ratio
3436| d4, d5, d6 hold some constants
3437 movel d7,a0 | d6-d7 will hold the ratio of the fractions
74a35b2b 3438 movel IMM (0),d6 |
0d64f74c
DE
3439 movel d6,d7
3440
aa2192f8 3441 moveq IMM (FLT_MANT_DIG+1),d3
0d64f74c
DE
34421: cmpl d0,d1 | is a < b?
3443 bhi 2f |
3444 bset d3,d6 | set a bit in d6
3445 subl d1,d0 | if a >= b a <-- a-b
3446 beq 3f | if a is zero, exit
34472: addl d0,d0 | multiply a by 2
9425fb04 3448#ifndef __mcoldfire__
0d64f74c 3449 dbra d3,1b
686cada4
ILT
3450#else
3451 subql IMM (1),d3
3452 bpl 1b
3453#endif
0d64f74c
DE
3454
3455| Now we keep going to set the sticky bit ...
aa2192f8 3456 moveq IMM (FLT_MANT_DIG),d3
0d64f74c
DE
34571: cmpl d0,d1
3458 ble 2f
3459 addl d0,d0
9425fb04 3460#ifndef __mcoldfire__
0d64f74c 3461 dbra d3,1b
686cada4
ILT
3462#else
3463 subql IMM(1),d3
3464 bpl 1b
3465#endif
74a35b2b 3466 movel IMM (0),d1
0d64f74c 3467 bra 3f
74a35b2b 34682: movel IMM (0),d1
9425fb04 3469#ifndef __mcoldfire__
74a35b2b
KR
3470 subw IMM (FLT_MANT_DIG),d3
3471 addw IMM (31),d3
686cada4
ILT
3472#else
3473 subl IMM (FLT_MANT_DIG),d3
3474 addl IMM (31),d3
3475#endif
0d64f74c
DE
3476 bset d3,d1
34773:
3478 movel d6,d0 | put the ratio in d0-d1
3479 movel a0,d7 | get sign back
3480
3481| Because of the normalization we did before we are guaranteed that
3482| d0 is smaller than 2^26 but larger than 2^24. Thus bit 26 is not set,
3483| bit 25 could be set, and if it is not set then bit 24 is necessarily set.
74a35b2b 3484 btst IMM (FLT_MANT_DIG+1),d0
0d64f74c 3485 beq 1f | if it is not set, then bit 24 is set
74a35b2b 3486 lsrl IMM (1),d0 |
9425fb04 3487#ifndef __mcoldfire__
74a35b2b 3488 addw IMM (1),d2 |
686cada4
ILT
3489#else
3490 addl IMM (1),d2 |
3491#endif
0d64f74c
DE
34921:
3493| Now round, check for over- and underflow, and exit.
aa2192f8 3494 moveq IMM (DIVIDE),d5
0d64f74c
DE
3495 bra Lround$exit
3496
3497Ldivsf$inop:
aa2192f8 3498 moveq IMM (DIVIDE),d5
0d64f74c
DE
3499 bra Lf$inop
3500
3501Ldivsf$overflow:
aa2192f8 3502 moveq IMM (DIVIDE),d5
0d64f74c
DE
3503 bra Lf$overflow
3504
3505Ldivsf$underflow:
aa2192f8 3506 moveq IMM (DIVIDE),d5
0d64f74c
DE
3507 bra Lf$underflow
3508
3509Ldivsf$a$0:
aa2192f8 3510 moveq IMM (DIVIDE),d5
0d64f74c
DE
3511| If a is zero check to see whether b is zero also. In that case return
3512| NaN; then check if b is NaN, and return NaN also in that case. Else
d55f9d23 3513| return a properly signed zero.
74a35b2b
KR
3514 andl IMM (0x7fffffff),d1 | clear sign bit and test b
3515 beq Lf$inop | if b is also zero return NaN
3516 cmpl IMM (INFINITY),d1 | check for NaN
3517 bhi Lf$inop |
d55f9d23 3518 movel d7,d0 | else return signed zero
a2ef3db7 3519 PICLEA SYM (_fpCCR),a0 |
74a35b2b 3520 movew IMM (0),a0@ |
9425fb04 3521#ifndef __mcoldfire__
74a35b2b 3522 moveml sp@+,d2-d7 |
e82673c4
RK
3523#else
3524 moveml sp@,d2-d7 |
3525 | XXX if frame pointer is ever removed, stack pointer must
3526 | be adjusted here.
3527#endif
74a35b2b
KR
3528 unlk a6 |
3529 rts |
0d64f74c
DE
3530
3531Ldivsf$b$0:
aa2192f8 3532 moveq IMM (DIVIDE),d5
0d64f74c
DE
3533| If we got here a is not zero. Check if a is NaN; in that case return NaN,
3534| else return +/-INFINITY. Remember that a is in d0 with the sign bit
3535| cleared already.
74a35b2b
KR
3536 cmpl IMM (INFINITY),d0 | compare d0 with INFINITY
3537 bhi Lf$inop | if larger it is NaN
3538 bra Lf$div$0 | else signal DIVIDE_BY_ZERO
0d64f74c
DE
3539
3540Ldivsf$inf:
aa2192f8 3541 moveq IMM (DIVIDE),d5
0d64f74c 3542| If a is INFINITY we have to check b
74a35b2b
KR
3543 cmpl IMM (INFINITY),d1 | compare b with INFINITY
3544 bge Lf$inop | if b is NaN or INFINITY return NaN
3545 bra Lf$overflow | else return overflow
0d64f74c
DE
3546
3547| If a number is denormalized we put an exponent of 1 but do not put the
3548| bit back into the fraction.
3549Ldivsf$a$den:
74a35b2b 3550 movel IMM (1),d2
0d64f74c
DE
3551 andl d5,d0
35521: addl d0,d0 | shift a left until bit FLT_MANT_DIG-1 is set
9425fb04 3553#ifndef __mcoldfire__
74a35b2b 3554 subw IMM (1),d2 | and adjust exponent
686cada4
ILT
3555#else
3556 subl IMM (1),d2 | and adjust exponent
3557#endif
74a35b2b 3558 btst IMM (FLT_MANT_DIG-1),d0
0d64f74c
DE
3559 bne Ldivsf$1
3560 bra 1b
3561
3562Ldivsf$b$den:
74a35b2b 3563 movel IMM (1),d3
0d64f74c
DE
3564 andl d5,d1
35651: addl d1,d1 | shift b left until bit FLT_MANT_DIG is set
9425fb04 3566#ifndef __mcoldfire__
74a35b2b 3567 subw IMM (1),d3 | and adjust exponent
686cada4
ILT
3568#else
3569 subl IMM (1),d3 | and adjust exponent
3570#endif
74a35b2b 3571 btst IMM (FLT_MANT_DIG-1),d1
0d64f74c
DE
3572 bne Ldivsf$2
3573 bra 1b
3574
3575Lround$exit:
3576| This is a common exit point for __mulsf3 and __divsf3.
3577
3578| First check for underlow in the exponent:
9425fb04 3579#ifndef __mcoldfire__
74a35b2b 3580 cmpw IMM (-FLT_MANT_DIG-1),d2
686cada4
ILT
3581#else
3582 cmpl IMM (-FLT_MANT_DIG-1),d2
3583#endif
0d64f74c
DE
3584 blt Lf$underflow
3585| It could happen that the exponent is less than 1, in which case the
3586| number is denormalized. In this case we shift right and adjust the
3587| exponent until it becomes 1 or the fraction is zero (in the latter case
3588| we signal underflow and return zero).
74a35b2b 3589 movel IMM (0),d6 | d6 is used temporarily
9425fb04 3590#ifndef __mcoldfire__
74a35b2b 3591 cmpw IMM (1),d2 | if the exponent is less than 1 we
686cada4
ILT
3592#else
3593 cmpl IMM (1),d2 | if the exponent is less than 1 we
3594#endif
0d64f74c 3595 bge 2f | have to shift right (denormalize)
686cada4 35961:
9425fb04 3597#ifndef __mcoldfire__
686cada4 3598 addw IMM (1),d2 | adjust the exponent
74a35b2b
KR
3599 lsrl IMM (1),d0 | shift right once
3600 roxrl IMM (1),d1 |
3601 roxrl IMM (1),d6 | d6 collect bits we would lose otherwise
3602 cmpw IMM (1),d2 | is the exponent 1 already?
686cada4
ILT
3603#else
3604 addql IMM (1),d2 | adjust the exponent
3605 lsrl IMM (1),d6
3606 btst IMM (0),d1
3607 beq 11f
3608 bset IMM (31),d6
360911: lsrl IMM (1),d1
3610 btst IMM (0),d0
3611 beq 10f
3612 bset IMM (31),d1
361310: lsrl IMM (1),d0
3614 cmpl IMM (1),d2 | is the exponent 1 already?
3615#endif
0d64f74c
DE
3616 beq 2f | if not loop back
3617 bra 1b |
3618 bra Lf$underflow | safety check, shouldn't execute '
36192: orl d6,d1 | this is a trick so we don't lose '
3620 | the extra bits which were flushed right
3621| Now call the rounding routine (which takes care of denormalized numbers):
a2ef3db7
BI
3622 lea pc@(Lround$0),a0 | to return from rounding routine
3623 PICLEA SYM (_fpCCR),a1 | check the rounding mode
9425fb04 3624#ifdef __mcoldfire__
686cada4
ILT
3625 clrl d6
3626#endif
0d64f74c
DE
3627 movew a1@(6),d6 | rounding mode in d6
3628 beq Lround$to$nearest
9425fb04 3629#ifndef __mcoldfire__
74a35b2b 3630 cmpw IMM (ROUND_TO_PLUS),d6
686cada4
ILT
3631#else
3632 cmpl IMM (ROUND_TO_PLUS),d6
3633#endif
0d64f74c
DE
3634 bhi Lround$to$minus
3635 blt Lround$to$zero
3636 bra Lround$to$plus
3637Lround$0:
3638| Here we have a correctly rounded result (either normalized or denormalized).
3639
3640| Here we should have either a normalized number or a denormalized one, and
3641| the exponent is necessarily larger or equal to 1 (so we don't have to '
3642| check again for underflow!). We have to check for overflow or for a
3643| denormalized number (which also signals underflow).
3644| Check for overflow (i.e., exponent >= 255).
9425fb04 3645#ifndef __mcoldfire__
74a35b2b 3646 cmpw IMM (0x00ff),d2
686cada4
ILT
3647#else
3648 cmpl IMM (0x00ff),d2
3649#endif
0d64f74c
DE
3650 bge Lf$overflow
3651| Now check for a denormalized number (exponent==0).
3652 movew d2,d2
3653 beq Lf$den
36541:
3655| Put back the exponents and sign and return.
9425fb04 3656#ifndef __mcoldfire__
74a35b2b 3657 lslw IMM (7),d2 | exponent back to fourth byte
686cada4
ILT
3658#else
3659 lsll IMM (7),d2 | exponent back to fourth byte
3660#endif
74a35b2b 3661 bclr IMM (FLT_MANT_DIG-1),d0
0d64f74c 3662 swap d0 | and put back exponent
9425fb04 3663#ifndef __mcoldfire__
0d64f74c 3664 orw d2,d0 |
686cada4
ILT
3665#else
3666 orl d2,d0
3667#endif
0d64f74c
DE
3668 swap d0 |
3669 orl d7,d0 | and sign also
3670
a2ef3db7 3671 PICLEA SYM (_fpCCR),a0
74a35b2b 3672 movew IMM (0),a0@
9425fb04 3673#ifndef __mcoldfire__
0d64f74c 3674 moveml sp@+,d2-d7
e82673c4
RK
3675#else
3676 moveml sp@,d2-d7
3677 | XXX if frame pointer is ever removed, stack pointer must
3678 | be adjusted here.
3679#endif
0d64f74c
DE
3680 unlk a6
3681 rts
3682
3683|=============================================================================
3684| __negsf2
3685|=============================================================================
3686
3687| This is trivial and could be shorter if we didn't bother checking for NaN '
3688| and +/-INFINITY.
3689
3690| float __negsf2(float);
2786eb8d 3691 FUNC(__negsf2)
0d64f74c 3692SYM (__negsf2):
9425fb04 3693#ifndef __mcoldfire__
74a35b2b 3694 link a6,IMM (0)
0d64f74c 3695 moveml d2-d7,sp@-
e82673c4
RK
3696#else
3697 link a6,IMM (-24)
3698 moveml d2-d7,sp@
3699#endif
aa2192f8 3700 moveq IMM (NEGATE),d5
0d64f74c 3701 movel a6@(8),d0 | get number to negate in d0
74a35b2b 3702 bchg IMM (31),d0 | negate
0d64f74c 3703 movel d0,d1 | make a positive copy
74a35b2b 3704 bclr IMM (31),d1 |
0d64f74c
DE
3705 tstl d1 | check for zero
3706 beq 2f | if zero (either sign) return +zero
74a35b2b 3707 cmpl IMM (INFINITY),d1 | compare to +INFINITY
0d64f74c
DE
3708 blt 1f |
3709 bhi Lf$inop | if larger (fraction not zero) is NaN
3710 movel d0,d7 | else get sign and return INFINITY
74a35b2b 3711 andl IMM (0x80000000),d7
0d64f74c 3712 bra Lf$infty
a2ef3db7 37131: PICLEA SYM (_fpCCR),a0
74a35b2b 3714 movew IMM (0),a0@
9425fb04 3715#ifndef __mcoldfire__
0d64f74c 3716 moveml sp@+,d2-d7
e82673c4
RK
3717#else
3718 moveml sp@,d2-d7
3719 | XXX if frame pointer is ever removed, stack pointer must
3720 | be adjusted here.
3721#endif
0d64f74c
DE
3722 unlk a6
3723 rts
74a35b2b 37242: bclr IMM (31),d0
0d64f74c
DE
3725 bra 1b
3726
3727|=============================================================================
3728| __cmpsf2
3729|=============================================================================
3730
3731GREATER = 1
3732LESS = -1
3733EQUAL = 0
3734
1a50d5e9
PB
3735| int __cmpsf2_internal(float, float, int);
3736SYM (__cmpsf2_internal):
9425fb04 3737#ifndef __mcoldfire__
74a35b2b 3738 link a6,IMM (0)
0d64f74c 3739 moveml d2-d7,sp@- | save registers
e82673c4
RK
3740#else
3741 link a6,IMM (-24)
3742 moveml d2-d7,sp@
3743#endif
aa2192f8 3744 moveq IMM (COMPARE),d5
0d64f74c
DE
3745 movel a6@(8),d0 | get first operand
3746 movel a6@(12),d1 | get second operand
3747| Check if either is NaN, and in that case return garbage and signal
3748| INVALID_OPERATION. Check also if either is zero, and clear the signs
3749| if necessary.
3750 movel d0,d6
74a35b2b 3751 andl IMM (0x7fffffff),d0
0d64f74c 3752 beq Lcmpsf$a$0
74a35b2b 3753 cmpl IMM (0x7f800000),d0
1a50d5e9 3754 bhi Lcmpf$inop
0d64f74c
DE
3755Lcmpsf$1:
3756 movel d1,d7
74a35b2b 3757 andl IMM (0x7fffffff),d1
0d64f74c 3758 beq Lcmpsf$b$0
74a35b2b 3759 cmpl IMM (0x7f800000),d1
1a50d5e9 3760 bhi Lcmpf$inop
0d64f74c
DE
3761Lcmpsf$2:
3762| Check the signs
3763 eorl d6,d7
3764 bpl 1f
3765| If the signs are not equal check if a >= 0
3766 tstl d6
3767 bpl Lcmpsf$a$gt$b | if (a >= 0 && b < 0) => a > b
3768 bmi Lcmpsf$b$gt$a | if (a < 0 && b >= 0) => a < b
37691:
3770| If the signs are equal check for < 0
3771 tstl d6
3772 bpl 1f
3773| If both are negative exchange them
9425fb04 3774#ifndef __mcoldfire__
0d64f74c 3775 exg d0,d1
686cada4
ILT
3776#else
3777 movel d0,d7
3778 movel d1,d0
3779 movel d7,d1
3780#endif
0d64f74c
DE
37811:
3782| Now that they are positive we just compare them as longs (does this also
3783| work for denormalized numbers?).
3784 cmpl d0,d1
3785 bhi Lcmpsf$b$gt$a | |b| > |a|
3786 bne Lcmpsf$a$gt$b | |b| < |a|
3787| If we got here a == b.
74a35b2b 3788 movel IMM (EQUAL),d0
9425fb04 3789#ifndef __mcoldfire__
0d64f74c 3790 moveml sp@+,d2-d7 | put back the registers
e82673c4
RK
3791#else
3792 moveml sp@,d2-d7
3793#endif
0d64f74c
DE
3794 unlk a6
3795 rts
3796Lcmpsf$a$gt$b:
74a35b2b 3797 movel IMM (GREATER),d0
9425fb04 3798#ifndef __mcoldfire__
0d64f74c 3799 moveml sp@+,d2-d7 | put back the registers
e82673c4
RK
3800#else
3801 moveml sp@,d2-d7
3802 | XXX if frame pointer is ever removed, stack pointer must
3803 | be adjusted here.
3804#endif
0d64f74c
DE
3805 unlk a6
3806 rts
3807Lcmpsf$b$gt$a:
74a35b2b 3808 movel IMM (LESS),d0
9425fb04 3809#ifndef __mcoldfire__
0d64f74c 3810 moveml sp@+,d2-d7 | put back the registers
e82673c4
RK
3811#else
3812 moveml sp@,d2-d7
3813 | XXX if frame pointer is ever removed, stack pointer must
3814 | be adjusted here.
3815#endif
0d64f74c
DE
3816 unlk a6
3817 rts
3818
3819Lcmpsf$a$0:
74a35b2b 3820 bclr IMM (31),d6
0d64f74c
DE
3821 bra Lcmpsf$1
3822Lcmpsf$b$0:
74a35b2b 3823 bclr IMM (31),d7
0d64f74c
DE
3824 bra Lcmpsf$2
3825
1a50d5e9
PB
3826Lcmpf$inop:
3827 movl a6@(16),d0
aa2192f8 3828 moveq IMM (INEXACT_RESULT+INVALID_OPERATION),d7
1a50d5e9
PB
3829 moveq IMM (SINGLE_FLOAT),d6
3830 PICJUMP $_exception_handler
3831
3832| int __cmpsf2(float, float);
2786eb8d 3833 FUNC(__cmpsf2)
1a50d5e9
PB
3834SYM (__cmpsf2):
3835 link a6,IMM (0)
3836 pea 1
3837 movl a6@(12),sp@-
3838 movl a6@(8),sp@-
c1af059c 3839 PICCALL SYM (__cmpsf2_internal)
1a50d5e9
PB
3840 unlk a6
3841 rts
3842
0d64f74c
DE
3843|=============================================================================
3844| rounding routines
3845|=============================================================================
3846
3847| The rounding routines expect the number to be normalized in registers
3848| d0-d1, with the exponent in register d2. They assume that the
3849| exponent is larger or equal to 1. They return a properly normalized number
3850| if possible, and a denormalized number otherwise. The exponent is returned
3851| in d2.
3852
3853Lround$to$nearest:
3854| We now normalize as suggested by D. Knuth ("Seminumerical Algorithms"):
3855| Here we assume that the exponent is not too small (this should be checked
3856| before entering the rounding routine), but the number could be denormalized.
3857
3858| Check for denormalized numbers:
74a35b2b 38591: btst IMM (FLT_MANT_DIG),d0
0d64f74c
DE
3860 bne 2f | if set the number is normalized
3861| Normalize shifting left until bit #FLT_MANT_DIG is set or the exponent
3862| is one (remember that a denormalized number corresponds to an
3863| exponent of -F_BIAS+1).
9425fb04 3864#ifndef __mcoldfire__
74a35b2b 3865 cmpw IMM (1),d2 | remember that the exponent is at least one
686cada4
ILT
3866#else
3867 cmpl IMM (1),d2 | remember that the exponent is at least one
3868#endif
0d64f74c
DE
3869 beq 2f | an exponent of one means denormalized
3870 addl d1,d1 | else shift and adjust the exponent
3871 addxl d0,d0 |
9425fb04 3872#ifndef __mcoldfire__
0d64f74c 3873 dbra d2,1b |
686cada4
ILT
3874#else
3875 subql IMM (1),d2
3876 bpl 1b
3877#endif
0d64f74c
DE
38782:
3879| Now round: we do it as follows: after the shifting we can write the
3880| fraction part as f + delta, where 1 < f < 2^25, and 0 <= delta <= 2.
3881| If delta < 1, do nothing. If delta > 1, add 1 to f.
3882| If delta == 1, we make sure the rounded number will be even (odd?)
3883| (after shifting).
74a35b2b 3884 btst IMM (0),d0 | is delta < 1?
0d64f74c
DE
3885 beq 2f | if so, do not do anything
3886 tstl d1 | is delta == 1?
3887 bne 1f | if so round to even
3888 movel d0,d1 |
74a35b2b 3889 andl IMM (2),d1 | bit 1 is the last significant bit
0d64f74c
DE
3890 addl d1,d0 |
3891 bra 2f |
74a35b2b 38921: movel IMM (1),d1 | else add 1
0d64f74c
DE
3893 addl d1,d0 |
3894| Shift right once (because we used bit #FLT_MANT_DIG!).
74a35b2b 38952: lsrl IMM (1),d0
0d64f74c
DE
3896| Now check again bit #FLT_MANT_DIG (rounding could have produced a
3897| 'fraction overflow' ...).
74a35b2b 3898 btst IMM (FLT_MANT_DIG),d0
0d64f74c 3899 beq 1f
74a35b2b 3900 lsrl IMM (1),d0
9425fb04 3901#ifndef __mcoldfire__
74a35b2b 3902 addw IMM (1),d2
686cada4
ILT
3903#else
3904 addql IMM (1),d2
3905#endif
0d64f74c
DE
39061:
3907| If bit #FLT_MANT_DIG-1 is clear we have a denormalized number, so we
3908| have to put the exponent to zero and return a denormalized number.
74a35b2b 3909 btst IMM (FLT_MANT_DIG-1),d0
0d64f74c
DE
3910 beq 1f
3911 jmp a0@
74a35b2b 39121: movel IMM (0),d2
0d64f74c
DE
3913 jmp a0@
3914
3915Lround$to$zero:
3916Lround$to$plus:
3917Lround$to$minus:
3918 jmp a0@
3919#endif /* L_float */
3920
3921| gcc expects the routines __eqdf2, __nedf2, __gtdf2, __gedf2,
3922| __ledf2, __ltdf2 to all return the same value as a direct call to
3923| __cmpdf2 would. In this implementation, each of these routines
3924| simply calls __cmpdf2. It would be more efficient to give the
3925| __cmpdf2 routine several names, but separating them out will make it
3926| easier to write efficient versions of these routines someday.
1a50d5e9
PB
3927| If the operands recompare unordered unordered __gtdf2 and __gedf2 return -1.
3928| The other routines return 1.
0d64f74c
DE
3929
3930#ifdef L_eqdf2
0d64f74c 3931 .text
2786eb8d 3932 FUNC(__eqdf2)
0d64f74c
DE
3933 .globl SYM (__eqdf2)
3934SYM (__eqdf2):
74a35b2b 3935 link a6,IMM (0)
1a50d5e9 3936 pea 1
0d64f74c
DE
3937 movl a6@(20),sp@-
3938 movl a6@(16),sp@-
3939 movl a6@(12),sp@-
3940 movl a6@(8),sp@-
1a50d5e9 3941 PICCALL SYM (__cmpdf2_internal)
0d64f74c 3942 unlk a6
0d64f74c
DE
3943 rts
3944#endif /* L_eqdf2 */
3945
3946#ifdef L_nedf2
0d64f74c 3947 .text
2786eb8d 3948 FUNC(__nedf2)
0d64f74c
DE
3949 .globl SYM (__nedf2)
3950SYM (__nedf2):
74a35b2b 3951 link a6,IMM (0)
1a50d5e9 3952 pea 1
0d64f74c
DE
3953 movl a6@(20),sp@-
3954 movl a6@(16),sp@-
3955 movl a6@(12),sp@-
3956 movl a6@(8),sp@-
1a50d5e9 3957 PICCALL SYM (__cmpdf2_internal)
0d64f74c 3958 unlk a6
0d64f74c
DE
3959 rts
3960#endif /* L_nedf2 */
3961
3962#ifdef L_gtdf2
3963 .text
2786eb8d 3964 FUNC(__gtdf2)
0d64f74c
DE
3965 .globl SYM (__gtdf2)
3966SYM (__gtdf2):
74a35b2b 3967 link a6,IMM (0)
1a50d5e9 3968 pea -1
0d64f74c
DE
3969 movl a6@(20),sp@-
3970 movl a6@(16),sp@-
3971 movl a6@(12),sp@-
3972 movl a6@(8),sp@-
1a50d5e9 3973 PICCALL SYM (__cmpdf2_internal)
0d64f74c 3974 unlk a6
0d64f74c
DE
3975 rts
3976#endif /* L_gtdf2 */
3977
3978#ifdef L_gedf2
0d64f74c 3979 .text
2786eb8d 3980 FUNC(__gedf2)
0d64f74c
DE
3981 .globl SYM (__gedf2)
3982SYM (__gedf2):
74a35b2b 3983 link a6,IMM (0)
1a50d5e9 3984 pea -1
0d64f74c
DE
3985 movl a6@(20),sp@-
3986 movl a6@(16),sp@-
3987 movl a6@(12),sp@-
3988 movl a6@(8),sp@-
1a50d5e9 3989 PICCALL SYM (__cmpdf2_internal)
0d64f74c 3990 unlk a6
0d64f74c
DE
3991 rts
3992#endif /* L_gedf2 */
3993
3994#ifdef L_ltdf2
0d64f74c 3995 .text
2786eb8d 3996 FUNC(__ltdf2)
0d64f74c
DE
3997 .globl SYM (__ltdf2)
3998SYM (__ltdf2):
74a35b2b 3999 link a6,IMM (0)
1a50d5e9 4000 pea 1
0d64f74c
DE
4001 movl a6@(20),sp@-
4002 movl a6@(16),sp@-
4003 movl a6@(12),sp@-
4004 movl a6@(8),sp@-
1a50d5e9 4005 PICCALL SYM (__cmpdf2_internal)
0d64f74c 4006 unlk a6
0d64f74c
DE
4007 rts
4008#endif /* L_ltdf2 */
4009
4010#ifdef L_ledf2
4011 .text
2786eb8d 4012 FUNC(__ledf2)
0d64f74c
DE
4013 .globl SYM (__ledf2)
4014SYM (__ledf2):
74a35b2b 4015 link a6,IMM (0)
1a50d5e9 4016 pea 1
0d64f74c
DE
4017 movl a6@(20),sp@-
4018 movl a6@(16),sp@-
4019 movl a6@(12),sp@-
4020 movl a6@(8),sp@-
1a50d5e9 4021 PICCALL SYM (__cmpdf2_internal)
0d64f74c 4022 unlk a6
0d64f74c
DE
4023 rts
4024#endif /* L_ledf2 */
4025
4026| The comments above about __eqdf2, et. al., also apply to __eqsf2,
4027| et. al., except that the latter call __cmpsf2 rather than __cmpdf2.
4028
4029#ifdef L_eqsf2
4030 .text
2786eb8d 4031 FUNC(__eqsf2)
0d64f74c
DE
4032 .globl SYM (__eqsf2)
4033SYM (__eqsf2):
74a35b2b 4034 link a6,IMM (0)
1a50d5e9 4035 pea 1
0d64f74c
DE
4036 movl a6@(12),sp@-
4037 movl a6@(8),sp@-
1a50d5e9 4038 PICCALL SYM (__cmpsf2_internal)
0d64f74c 4039 unlk a6
0d64f74c
DE
4040 rts
4041#endif /* L_eqsf2 */
4042
4043#ifdef L_nesf2
4044 .text
2786eb8d 4045 FUNC(__nesf2)
0d64f74c
DE
4046 .globl SYM (__nesf2)
4047SYM (__nesf2):
74a35b2b 4048 link a6,IMM (0)
1a50d5e9 4049 pea 1
0d64f74c
DE
4050 movl a6@(12),sp@-
4051 movl a6@(8),sp@-
1a50d5e9 4052 PICCALL SYM (__cmpsf2_internal)
0d64f74c 4053 unlk a6
0d64f74c
DE
4054 rts
4055#endif /* L_nesf2 */
4056
4057#ifdef L_gtsf2
4058 .text
2786eb8d 4059 FUNC(__gtsf2)
0d64f74c
DE
4060 .globl SYM (__gtsf2)
4061SYM (__gtsf2):
74a35b2b 4062 link a6,IMM (0)
1a50d5e9 4063 pea -1
0d64f74c
DE
4064 movl a6@(12),sp@-
4065 movl a6@(8),sp@-
1a50d5e9 4066 PICCALL SYM (__cmpsf2_internal)
0d64f74c 4067 unlk a6
0d64f74c
DE
4068 rts
4069#endif /* L_gtsf2 */
4070
4071#ifdef L_gesf2
4072 .text
2786eb8d 4073 FUNC(__gesf2)
0d64f74c
DE
4074 .globl SYM (__gesf2)
4075SYM (__gesf2):
74a35b2b 4076 link a6,IMM (0)
1a50d5e9 4077 pea -1
0d64f74c
DE
4078 movl a6@(12),sp@-
4079 movl a6@(8),sp@-
1a50d5e9 4080 PICCALL SYM (__cmpsf2_internal)
0d64f74c 4081 unlk a6
0d64f74c
DE
4082 rts
4083#endif /* L_gesf2 */
4084
4085#ifdef L_ltsf2
4086 .text
2786eb8d 4087 FUNC(__ltsf2)
0d64f74c
DE
4088 .globl SYM (__ltsf2)
4089SYM (__ltsf2):
74a35b2b 4090 link a6,IMM (0)
1a50d5e9 4091 pea 1
0d64f74c
DE
4092 movl a6@(12),sp@-
4093 movl a6@(8),sp@-
1a50d5e9 4094 PICCALL SYM (__cmpsf2_internal)
0d64f74c 4095 unlk a6
0d64f74c
DE
4096 rts
4097#endif /* L_ltsf2 */
4098
4099#ifdef L_lesf2
4100 .text
2786eb8d 4101 FUNC(__lesf2)
0d64f74c
DE
4102 .globl SYM (__lesf2)
4103SYM (__lesf2):
74a35b2b 4104 link a6,IMM (0)
1a50d5e9 4105 pea 1
0d64f74c
DE
4106 movl a6@(12),sp@-
4107 movl a6@(8),sp@-
1a50d5e9 4108 PICCALL SYM (__cmpsf2_internal)
0d64f74c 4109 unlk a6
0d64f74c
DE
4110 rts
4111#endif /* L_lesf2 */
74cc88a6
MK
4112
4113#if defined (__ELF__) && defined (__linux__)
4114 /* Make stack non-executable for ELF linux targets. */
4115 .section .note.GNU-stack,"",@progbits
4116#endif