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