1 /* libgcc routines for
68000 w
/o floating
-point hardware.
2 Copyright
(C
) 1994, 1996, 1997, 1998 Free Software Foundation
, Inc.
4 This file is part of GNU CC.
6 GNU CC is free software
; you can redistribute it and/or modify it
7 under the terms of the GNU General
Public License as published by the
8 Free Software Foundation
; either version 2, or (at your option) any
11 In addition to the permissions
in the GNU General
Public License
, the
12 Free Software Foundation gives you unlimited permission to link the
13 compiled version of
this file with other programs
, and to distribute
14 those programs without any restriction coming from the use of
this
15 file.
(The General
Public License restrictions do apply
in other
16 respects
; for example, they cover modification of the file, and
17 distribution when
not linked
into another program.
)
19 This file is distributed
in the hope that it will be useful
, but
20 WITHOUT ANY WARRANTY
; without even the implied warranty of
21 MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22 General
Public License for more details.
24 You should have received a copy of the GNU General
Public License
25 along with
this program
; see the file COPYING. If not, write to
26 the Free Software Foundation
, 59 Temple Place
- Suite
330,
27 Boston
, MA
02111-1307, USA.
*/
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.
*/
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
41 /* These are predefined by new versions of GNU cpp.
*/
43 #ifndef __USER_LABEL_PREFIX__
44 #define __USER_LABEL_PREFIX__ _
47 #ifndef __REGISTER_PREFIX__
48 #define __REGISTER_PREFIX__
51 #ifndef __IMMEDIATE_PREFIX__
52 #define __IMMEDIATE_PREFIX__ #
55 /* ANSI concatenation macros.
*/
57 #define CONCAT1
(a
, b
) CONCAT2
(a
, b
)
58 #define CONCAT2
(a
, b
) a ## b
60 /* Use the right prefix for
global labels.
*/
62 #define SYM
(x
) CONCAT1
(__USER_LABEL_PREFIX__
, x
)
64 /* Use the right prefix for registers.
*/
66 #define REG
(x
) CONCAT1
(__REGISTER_PREFIX__
, x
)
68 /* Use the right prefix for immediate values.
*/
70 #define IMM
(x
) CONCAT1
(__IMMEDIATE_PREFIX__
, x
)
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
!).
96 | Starting
date: 21 October
, 1990
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
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.
112 |
=============================================================================
114 |
=============================================================================
116 |
This is the floating point condition code register
(_fpCCR
):
119 | short _exception_bits;
120 | short _trap_enable_bits;
121 | short _sticky_bits;
122 | short _rounding_mode;
124 | short _last_operation;
148 .
word ROUND_TO_NEAREST
161 EBITS
= __exception_bits
- SYM
(_fpCCR
)
162 TRAPE
= __trap_enable_bits
- SYM
(_fpCCR
)
163 STICK
= __sticky_bits
- SYM
(_fpCCR
)
164 ROUND
= __rounding_mode
- SYM
(_fpCCR
)
165 FORMT
= __format
- SYM
(_fpCCR
)
166 LASTO
= __last_operation
- SYM
(_fpCCR
)
167 OPER1
= __operand1
- SYM
(_fpCCR
)
168 OPER2
= __operand2
- SYM
(_fpCCR
)
170 | The following exception types are
supported:
171 INEXACT_RESULT
= 0x0001
174 DIVIDE_BY_ZERO
= 0x0008
175 INVALID_OPERATION
= 0x0010
177 | The allowed rounding modes
are:
179 ROUND_TO_NEAREST
= 0 | round result to nearest representable value
180 ROUND_TO_ZERO
= 1 | round result towards zero
181 ROUND_TO_PLUS
= 2 | round result towards plus infinity
182 ROUND_TO_MINUS
= 3 | round result towards minus infinity
184 | The allowed values of format
are:
190 | The allowed values for the last operation
are:
200 |
=============================================================================
201 | __clear_sticky_bits
202 |
=============================================================================
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
).
209 .globl SYM
(__clear_sticky_bit
)
214 | void __clear_sticky_bits
(void
);
215 SYM
(__clear_sticky_bit
):
218 movew IMM
(0),a0@
(STICK
)
224 |
=============================================================================
225 | $_exception_handler
226 |
=============================================================================
228 .globl $_exception_handler
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
).
250 movew d7
,a0@
(EBITS
) | set __exception_bits
252 orw d7
,a0@
(STICK
) |
and __sticky_bits
258 movew d6
,a0@
(FORMT
) |
and __format
259 movew d5
,a0@
(LASTO
) |
and __last_operation
261 | Now put the operands
in place:
263 cmpw IMM
(SINGLE_FLOAT
),d6
265 cmpl IMM
(SINGLE_FLOAT
),d6
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)
273 1: movel a6@
(8),a0@
(OPER1
)
274 movel a6@
(12),a0@
(OPER2
)
276 |
And check whether the exception is trap
-enabled:
278 andw a0@
(TRAPE
),d7 | is exception trap
-enabled
?
285 pea SYM
(_fpCCR
) | yes
, push address of _fpCCR
286 trap IMM
(FPTRAP
) |
and trap
288 1: moveml
sp@
+,d2
-d7 | restore data registers
291 | XXX if frame pointer is ever removed
, stack pointer must
296 #endif
/* L_floatex
*/
301 .globl SYM
(__mulsi3
)
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
*/
314 movew
sp@
(6), d1
/* x1
-> d1
*/
315 muluw
sp@
(10), d1
/* x1
*y1
*/
319 #endif
/* L_mulsi3
*/
324 .globl SYM
(__udivsi3
)
328 movel
sp@
(12), d1
/* d1
= divisor
*/
329 movel
sp@
(8), d0
/* d0
= dividend
*/
331 cmpl IMM
(0x10000), d1
/* divisor
>= 2 ^
16 ? */
332 jcc L3
/* then try next algorithm
*/
336 divu d1
, d2
/* high quotient
in lower
word */
337 movew d2
, d0
/* save
high quotient
*/
339 movew
sp@
(10), d2
/* get
low dividend
+ high rest
*/
340 divu d1
, d2
/* low quotient
*/
344 L3: movel d1
, d2
/* use d2 as divisor backup
*/
345 L4: lsrl IMM
(1), d1
/* shift divisor
*/
346 lsrl IMM
(1), d0
/* shift dividend
*/
347 cmpl IMM
(0x10000), d1
/* still divisor
>= 2 ^
16 ? */
349 divu d1
, d0
/* now we have
16 bit divisor
*/
350 andl IMM
(0xffff), d0
/* mask out divisor
, ignore remainder
*/
352 /* Multiply the
16 bit tentative quotient with the
32 bit divisor. Because of
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.
*/
356 mulu d0
, d1
/* low part
, 32 bits
*/
358 mulu d0
, d2
/* high part
, at most
17 bits
*/
359 swap d2
/* align high part with
low part
*/
360 tstw d2
/* high part
17 bits
? */
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 */
366 L5: subql IMM
(1), d0
/* adjust quotient
*/
371 #else
/* __mcf5200__
*/
373 /* Coldfire implementation of non
-restoring division algorithm from
374 Hennessy
& Patterson
, Appendix A.
*/
381 L1: addl d0
,d0 | shift reg pair
(p
,a
) one bit left
383 movl d2
,d3 | subtract b from p
, store
in tmp.
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.
390 moveml
sp@
,d2
-d4 | restore data registers
393 #endif
/* __mcf5200__
*/
395 #endif
/* L_udivsi3
*/
400 .globl SYM
(__divsi3
)
404 moveq IMM
(1), d2
/* sign of result stored
in d2
(=1 or =-1) */
405 movel
sp@
(12), d1
/* d1
= divisor
*/
409 negb d2
/* change sign because divisor
<0 */
411 negl d2
/* change sign because divisor
<0 */
413 L1: movel
sp@
(8), d0
/* d0
= dividend
*/
424 jbsr SYM
(__udivsi3
) /* divide abs
(dividend
) by abs
(divisor
) */
433 #endif
/* L_divsi3
*/
438 .globl SYM
(__umodsi3
)
440 movel
sp@
(8), d1
/* d1
= divisor
*/
441 movel
sp@
(4), d0
/* d0
= dividend
*/
446 movel
sp@
(8), d1
/* d1
= divisor
*/
450 jbsr SYM
(__mulsi3
) /* d0
= (a
/b
)*b
*/
455 movel
sp@
(4), d1
/* d1
= dividend
*/
456 subl d0
, d1
/* d1
= a
- (a
/b
)*b
*/
459 #endif
/* L_umodsi3
*/
464 .globl SYM
(__modsi3
)
466 movel
sp@
(8), d1
/* d1
= divisor
*/
467 movel
sp@
(4), d0
/* d0
= dividend
*/
472 movel
sp@
(8), d1
/* d1
= divisor
*/
476 jbsr SYM
(__mulsi3
) /* d0
= (a
/b
)*b
*/
481 movel
sp@
(4), d1
/* d1
= dividend
*/
482 subl d0
, d1
/* d1
= a
- (a
/b
)*b
*/
485 #endif
/* L_modsi3
*/
491 .globl $_exception_handler
493 QUIET_NaN
= 0xffffffff
497 DBL_MAX_EXP
= D_MAX_EXP
- D_BIAS
498 DBL_MIN_EXP
= 1 - D_BIAS
501 INEXACT_RESULT
= 0x0001
504 DIVIDE_BY_ZERO
= 0x0008
505 INVALID_OPERATION
= 0x0010
519 ROUND_TO_NEAREST
= 0 | round result to nearest representable value
520 ROUND_TO_ZERO
= 1 | round result towards zero
521 ROUND_TO_PLUS
= 2 | round result towards plus infinity
522 ROUND_TO_MINUS
= 3 | round result towards minus infinity
526 .globl SYM
(__adddf3
)
527 .globl SYM
(__subdf3
)
528 .globl SYM
(__muldf3
)
529 .globl SYM
(__divdf3
)
530 .globl SYM
(__negdf2
)
531 .globl SYM
(__cmpdf2
)
536 | These are common routines to return
and signal exceptions.
539 | Return
and signal a denormalized number
541 movew IMM
(INEXACT_RESULT
+UNDERFLOW
),d7
542 moveq IMM
(DOUBLE_FLOAT
),d6
543 jmp $_exception_handler
547 | Return a properly signed INFINITY
and set the exception flags
548 movel IMM
(0x7ff00000),d0
551 movew IMM
(INEXACT_RESULT
+OVERFLOW
),d7
552 moveq IMM
(DOUBLE_FLOAT
),d6
553 jmp $_exception_handler
556 | Return
0 and set the exception flags
559 movew IMM
(INEXACT_RESULT
+UNDERFLOW
),d7
560 moveq IMM
(DOUBLE_FLOAT
),d6
561 jmp $_exception_handler
564 | Return a quiet NaN
and set the exception flags
565 movel IMM
(QUIET_NaN
),d0
567 movew IMM
(INEXACT_RESULT
+INVALID_OPERATION
),d7
568 moveq IMM
(DOUBLE_FLOAT
),d6
569 jmp $_exception_handler
572 | Return a properly signed INFINITY
and set the exception flags
573 movel IMM
(0x7ff00000),d0
576 movew IMM
(INEXACT_RESULT
+DIVIDE_BY_ZERO
),d7
577 moveq IMM
(DOUBLE_FLOAT
),d6
578 jmp $_exception_handler
580 |
=============================================================================
581 |
=============================================================================
582 | double precision routines
583 |
=============================================================================
584 |
=============================================================================
586 | A double precision floating point number
(double
) has the
format:
589 | unsigned int sign : 1; /* sign bit */
590 | unsigned int exponent : 11; /* exponent, shifted by 126 */
591 | unsigned int fraction : 52; /* fraction */
594 | Thus sizeof
(double
) = 8 (64 bits
).
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
600 |
=============================================================================
602 |
=============================================================================
604 | double __subdf3
(double
, double
);
606 bchg IMM
(31),sp@
(12) | change sign of second operand
607 |
and fall through
, so we always
add
608 |
=============================================================================
610 |
=============================================================================
612 | double __adddf3
(double
, double
);
615 link a6
,IMM
(0) | everything will be done
in registers
616 moveml d2
-d7
,sp@
- | save all data registers
and a2
(but d0
-d1
)
621 movel a6@
(8),d0 | get first operand
623 movel a6@
(16),d2 | get second operand
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
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
636 andl IMM
(0x80000000),d7 | isolate a
's sign bit '
637 swap d6 |
and also b
's sign bit '
639 andw IMM
(0x8000),d6 |
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
647 movel d7
,a0 | now save d7
into a0
, so d7 is free to
650 | Get the exponents
and check for denormalized
and/or infinity.
652 movel IMM
(0x001fffff),d6 |
mask for the fraction
653 movel IMM
(0x00200000),d7 |
mask to put hidden bit back
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
662 orl d7
,d0 |
and put hidden bit back
664 swap d4 | shift right exponent so that it starts
666 lsrw IMM
(5),d4 |
in bit
0 and not bit
20
668 lsrl IMM
(5),d4 |
in bit
0 and not bit
20
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
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
680 swap d5 | shift right exponent so that it starts
682 lsrw IMM
(5),d5 |
in bit
0 and not bit
20
684 lsrl IMM
(5),d5 |
in bit
0 and not bit
20
687 | Now we have b
's exponent in d5 and fraction in d2-d3. '
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.
697 moveml a2
-a3
,sp@
- | save the address registers
704 movel d4
,a2 | save the exponents
707 movel IMM
(0),d7 |
and move the numbers around
714 | Here we shift the numbers until the exponents are the same
, and put
715 | the largest exponent
in a2.
717 exg d4
,a2 | get exponents back
719 cmpw d4
,d5 | compare the exponents
721 movel d4
,a4 | get exponents back
727 cmpl d4
,d5 | compare the exponents
729 beq Ladddf
$3 | if equal don
't shift '
730 bhi
9f | branch if second exponent is higher
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:
734 1: movew d4
,d2 | move largest exponent to d2
736 subw d5
,d2 |
and subtract second exponent
737 exg d4
,a2 | get back the longs we saved
740 subl d5
,d2 |
and subtract second exponent
741 movel d4
,a4 | get back the longs we saved
748 | if difference is too
large we don
't shift (actually, we can just exit) '
750 cmpw IMM
(DBL_MANT_DIG
+2),d2
752 cmpl IMM
(DBL_MANT_DIG
+2),d2
756 cmpw IMM
(32),d2 | if difference
>= 32, shift by longs
758 cmpl IMM
(32),d2 | if difference
>= 32, shift by longs
763 cmpw IMM
(16),d2 | if difference
>= 16, shift by words
765 cmpl IMM
(16),d2 | if difference
>= 16, shift by words
768 bra
3f |
enter dbra
loop
832 subw d5
,d6 | keep d5
(largest exponent
) in d4
847 | if difference is too
large we don
't shift (actually, we can just exit) '
849 cmpw IMM
(DBL_MANT_DIG
+2),d6
851 cmpl IMM
(DBL_MANT_DIG
+2),d6
855 cmpw IMM
(32),d6 | if difference
>= 32, shift by longs
857 cmpl IMM
(32),d6 | if difference
>= 32, shift by longs
862 cmpw IMM
(16),d6 | if difference
>= 16, shift by words
864 cmpl IMM
(16),d6 | if difference
>= 16, shift by words
867 bra
3f |
enter dbra
loop
939 | Now we have the numbers
in d0
--d3
and d4
--d7
, the exponent
in a2
, and
942 | Here we have to decide whether to
add or subtract the
numbers:
944 exg d7
,a0 | get the signs
945 exg d6
,a3 | a3 is free to be used
955 movew IMM
(0),d7 | get a
's sign in d7 '
957 movew IMM
(0),d6 |
and b
's sign in d6 '
958 eorl d7
,d6 | compare the signs
959 bmi Lsubdf
$0 | if the signs are different we have
962 exg d7
,a0 | else we
add the numbers
977 movel a2
,d4 | return exponent to d4
979 andl IMM
(0x80000000),d7 | d7 now has the sign
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
).
991 | As
in the addition
(not in the subtraction
!) we could have set
992 | one more bit we check
this:
993 btst IMM
(DBL_MANT_DIG
+1),d0
1018 lea Ladddf
$5,a0 | to return from rounding routine
1019 lea SYM
(_fpCCR
),a1 | check the rounding mode
1023 movew a1@
(6),d6 | rounding mode
in d6
1024 beq Lround$to$nearest
1026 cmpw IMM
(ROUND_TO_PLUS
),d6
1028 cmpl IMM
(ROUND_TO_PLUS
),d6
1034 | Put back the exponent
and check for overflow
1036 cmpw IMM
(0x7ff),d4 | is the exponent big
?
1038 cmpl IMM
(0x7ff),d4 | is the exponent big
?
1041 bclr IMM
(DBL_MANT_DIG
-1),d0
1043 lslw IMM
(4),d4 | put exponent back
into position
1045 lsll IMM
(4),d4 | put exponent back
into position
1060 | Here we do the subtraction.
1062 exg d7
,a0 | put sign back
in a0
1076 beq Ladddf$
ret$1 | if zero just exit
1077 bpl
1f | if positive skip the following
1079 bchg IMM
(31),d7 | change sign bit
in d7
1083 negxl d1 |
and negate result
1086 movel a2
,d4 | return exponent to d4
1088 andl IMM
(0x80000000),d7 | isolate sign bit
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
).
1099 | As
in the addition
(not in the subtraction
!) we could have set
1100 | one more bit we check
this:
1101 btst IMM
(DBL_MANT_DIG
+1),d0
1126 lea Lsubdf
$1,a0 | to return from rounding routine
1127 lea SYM
(_fpCCR
),a1 | check the rounding mode
1131 movew a1@
(6),d6 | rounding mode
in d6
1132 beq Lround$to$nearest
1134 cmpw IMM
(ROUND_TO_PLUS
),d6
1136 cmpl IMM
(ROUND_TO_PLUS
),d6
1142 | Put back the exponent
and sign
(we don
't have overflow). '
1143 bclr IMM
(DBL_MANT_DIG
-1),d0
1145 lslw IMM
(4),d4 | put exponent back
into position
1147 lsll IMM
(4),d4 | put exponent back
into position
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
).
1174 moveml
sp@
+,d2
-d7 | restore data registers
1177 | XXX if frame pointer is ever removed
, stack pointer must
1180 unlk a6 |
and return
1196 moveml
sp@
+,d2
-d7 | restore data registers
1199 | XXX if frame pointer is ever removed
, stack pointer must
1202 unlk a6 |
and return
1206 movel d7
,d4 | d7 contains
0x00200000
1210 movel d7
,d5 | d7 contains
0x00200000
1215 | Return b
(if a is zero
)
1224 | Check for NaN
and +/-INFINITY.
1226 andl IMM
(0x80000000),d7 |
1228 cmpl IMM
(0x7ff00000),d0 |
1230 movel d0
,d0 | check for zero
, since we don
't '
1231 bne Ladddf$
ret | want to return
-0 by mistake
1235 andl IMM
(0x000fffff),d0 | check for NaN
(nonzero fraction
)
1242 moveml
sp@
+,a2
-a3 | restore regs
and exit
1253 orl d7
,d0 | put sign bit back
1258 | XXX if frame pointer is ever removed
, stack pointer must
1265 | Return a denormalized number.
1267 lsrl IMM
(1),d0 | shift right once more
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
)
1286 movel IMM
(0x7ff00000),d4 | useful constant
(INFINITY
)
1287 movel d0
,d7 | save sign bits
1289 bclr IMM
(31),d0 | clear sign bits
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
1296 tstl d1 | d1
> 0, a is NaN
1298 2: cmpl d4
,d2 | check now b
(d1
)
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
1306 | are adding
or subtracting them.
1307 eorl d7
,d6 | to check sign bits
1309 andl IMM
(0x80000000),d7 | get
(common
) sign bit
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
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
1320 andl IMM
(0x80000000),d7 | get a
's sign bit '
1321 cmpl d4
,d0 |
test now for infinity
1322 beq Ld$infty | if a is INFINITY return with
this sign
1323 bchg IMM
(31),d7 | else we know b is INFINITY
and has
1324 bra Ld$infty | the opposite sign
1326 |
=============================================================================
1328 |
=============================================================================
1330 | double __muldf3
(double
, double
);
1339 movel a6@
(8),d0 | get a
into d0
-d1
1341 movel a6@
(16),d2 |
and b
into d2
-d3
1343 movel d0
,d7 | d7 will hold the sign of the product
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
)
1350 bclr IMM
(31),d0 | get rid of a
's sign bit '
1353 beq Lmuldf
$a$0 | branch if a is zero
1355 bclr IMM
(31),d2 | get rid of b
's sign bit '
1358 beq Lmuldf
$b$0 | branch if b is zero
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 ...
1366 | Here we have both numbers finite
and nonzero
(and with no sign bit
).
1367 | Now we get the exponents
into d4
and d5.
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
1382 orl IMM
(0x00100000),d2 |
and put hidden bit back
1391 addw d5
,d4 |
add exponents
1392 subw IMM
(D_BIAS
+1),d4 |
and subtract bias
(plus one
)
1394 addl d5
,d4 |
add exponents
1395 subl IMM
(D_BIAS
+1),d4 |
and subtract bias
(plus one
)
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.
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.
1409 moveml a2
-a3
,sp@
- | save a2
and a3 for temporary use
1415 movel IMM
(0),a2 | a2 is a null register
1416 movel d4
,a3 |
and a3 will preserve the exponent
1418 | First
, shift d2
-d3 so bit
20 becomes bit
31:
1420 rorl IMM
(5),d2 | rotate d2
5 places right
1421 swap d2 |
and swap it
1422 rorl IMM
(5),d3 | do the same thing with d3
1424 movew d3
,d6 | get the rightmost
11 bits of d3
1425 andw IMM
(0x07ff),d6 |
1426 orw d6
,d2 |
and put them
into d2
1427 andw IMM
(0xf800),d3 | clear those bits
in d3
1429 moveq IMM
(11),d7 | left shift d2
11 bits
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
1436 orl d6
,d2 | stick them at the
end of d2
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
)
1448 | We use a1 as
counter:
1449 movel IMM
(DBL_MANT_DIG
-1),a1
1460 exg d7
,a1 | put counter back
in a1
1466 addl d3
,d3 | shift sum once left
1472 bcc
2f | if bit clear skip the following
1480 addl d5
,d3 | else
add a to the sum
1493 exg d7
,a1 | put counter
in d7
1494 dbf d7
,1b | decrement
and branch
1503 movel a3
,d4 | restore exponent
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.
1553 | Now round
, check for over
- and underflow
, and exit.
1554 movel a0
,d7 | get sign bit back
into d7
1555 movew IMM
(MULTIPLY
),d5
1557 btst IMM
(DBL_MANT_DIG
+1-32),d0
1574 movew IMM
(MULTIPLY
),d5
1578 movew IMM
(MULTIPLY
),d5
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
)
1585 movew IMM
(MULTIPLY
),d5
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
1591 | If either number is zero return zero
, unless the other is
+/-INFINITY
or
1592 | NaN
, in which case we return NaN.
1594 movew IMM
(MULTIPLY
),d5
1596 exg d2
,d0 | put b
(==0) into d0
-d1
1597 exg d3
,d1 |
and a
(with sign bit cleared
) into d2
-d3
1608 movel a6@
(16),d2 | put b
into d2
-d3 again
1610 bclr IMM
(31),d2 | clear sign bit
1611 1: cmpl IMM
(0x7ff00000),d2 | check for non
-finiteness
1612 bge Ld$inop |
in case NaN
or +/-INFINITY return NaN
1619 | XXX if frame pointer is ever removed
, stack pointer must
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.
1632 1: addl d1
,d1 | shift a left until bit
20 is set
1635 subw IMM
(1),d4 |
and adjust exponent
1637 subl IMM
(1),d4 |
and adjust exponent
1646 1: addl d3
,d3 | shift b left until bit
20 is set
1649 subw IMM
(1),d5 |
and adjust exponent
1651 subql IMM
(1),d5 |
and adjust exponent
1658 |
=============================================================================
1660 |
=============================================================================
1662 | double __divdf3
(double
, double
);
1671 movel a6@
(8),d0 | get a
into d0
-d1
1673 movel a6@
(16),d2 |
and b
into d2
-d3
1675 movel d0
,d7 | d7 will hold the sign of the result
1677 andl IMM
(0x80000000),d7
1678 movel d7
,a0 | save sign
into a0
1679 movel IMM
(0x7ff00000),d7 | useful constant
(+INFINITY
)
1680 movel d7
,d6 | another
(mask for fraction
)
1682 bclr IMM
(31),d0 | get rid of a
's sign bit '
1685 beq Ldivdf
$a$0 | branch if a is zero
1687 bclr IMM
(31),d2 | get rid of b
's sign bit '
1690 beq Ldivdf
$b$0 | branch if b is zero
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
1707 orl IMM
(0x00100000),d0 |
and put hidden bit back
1708 swap d4 | I like exponents
in the first
byte
1718 orl IMM
(0x00100000),d2
1727 subw d5
,d4 | subtract exponents
1728 addw IMM
(D_BIAS
),d4 |
and add bias
1730 subl d5
,d4 | subtract exponents
1731 addl IMM
(D_BIAS
),d4 |
and add bias
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
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
1749 movel IMM
(0),d6 | d6
-d7 will hold the result
1751 movel IMM
(0),a1 |
and a1 will hold the sticky bit
1753 movel IMM
(DBL_MANT_DIG
-32+1),d5
1755 1: 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
1759 subxl d2
,d0 | a
<-- a
- b
1760 bset d5
,d6 | set the corresponding bit
in d6
1761 3: addl d1
,d1 | shift a by
1
1764 dbra d5
,1b |
and branch back
1770 4: cmpl d1
,d3 | here d0
==d2
, so check d1
and d3
1771 bhi
3b | if d1
> d2 skip the subtraction
1772 bra
2b | else go do it
1774 | Here we have to start setting the bits
in the second long.
1775 movel IMM
(31),d5 | again d5 is counter
1777 1: 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
1781 subxl d2
,d0 | a
<-- a
- b
1782 bset d5
,d7 | set the corresponding bit
in d7
1783 3: addl d1
,d1 | shift a by
1
1786 dbra d5
,1b |
and branch back
1792 4: cmpl d1
,d3 | here d0
==d2
, so check d1
and d3
1793 bhi
3b | if d1
> d2 skip the subtraction
1794 bra
2b | else go do it
1796 | Now go ahead checking until we hit a one
, which we store
in d2.
1797 movel IMM
(DBL_MANT_DIG
),d5
1798 1: cmpl d2
,d0 | is a
< b
?
1799 bhi
4f | if b
< a
, exit
1800 beq
3f | if d0
==d2 check d1
and d3
1801 2: addl d1
,d1 | shift a by
1
1804 dbra d5
,1b |
and branch back
1809 movel IMM
(0),d2 | here no sticky bit was found
1812 3: cmpl d1
,d3 | here d0
==d2
, so check d1
and d3
1813 bhi
2b | if d1
> d2 go back
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). '
1820 subw IMM
(DBL_MANT_DIG
),d5
1824 subl IMM
(DBL_MANT_DIG
),d5
1838 | Finally we are finished
! Move the longs
in the address registers to
1839 | their final
destination:
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
1848 btst IMM
(DBL_MANT_DIG
-32+1),d0
1873 | Now round
, check for over
- and underflow
, and exit.
1874 movel a0
,d7 | restore sign bit to d7
1875 movew IMM
(DIVIDE
),d5
1879 movew IMM
(DIVIDE
),d5
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
1886 movew IMM
(DIVIDE
),d5
1890 beq Ld$inop | if b is also zero return NaN
1891 cmpl IMM
(0x7ff00000),d2 | check for NaN
1896 1: movel IMM
(0),d0 | else return zero
1898 lea SYM
(_fpCCR
),a0 | clear exception flags
1904 | XXX if frame pointer is ever removed
, stack pointer must
1911 movew IMM
(DIVIDE
),d5
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
1915 movel a0
,d7 | put a
's sign bit back in d7 '
1916 cmpl IMM
(0x7ff00000),d0 | compare d0 with INFINITY
1917 bhi Ld$inop | if larger it is NaN
1920 bra Ld
$div
$0 | else signal DIVIDE_BY_ZERO
1923 movew IMM
(DIVIDE
),d5
1924 | If d2
== 0x7ff00000 we have to check d3.
1926 bne Ld$inop | if d3
<> 0, b is NaN
1927 bra Ld$underflow | else b is
+/-INFINITY
, so signal underflow
1930 movew IMM
(DIVIDE
),d5
1931 | If d0
== 0x7ff00000 we have to check 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
1939 bra Ld$overflow | else return overflow
1941 | If a number is denormalized we put an exponent of
1 but do
not put the
1942 | bit back
into the fraction.
1946 1: addl d1
,d1 | shift a left until bit
20 is set
1949 subw IMM
(1),d4 |
and adjust exponent
1951 subl IMM
(1),d4 |
and adjust exponent
1953 btst IMM
(DBL_MANT_DIG
-32-1),d0
1960 1: addl d3
,d3 | shift b left until bit
20 is set
1963 subw IMM
(1),d5 |
and adjust exponent
1965 subql IMM
(1),d5 |
and adjust exponent
1967 btst IMM
(DBL_MANT_DIG
-32-1),d2
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.
1976 | First check for underlow
in the
exponent:
1978 cmpw IMM
(-DBL_MANT_DIG
-1),d4
1980 cmpl IMM
(-DBL_MANT_DIG
-1),d4
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
).
1988 movel IMM
(0),d6 | use d6
-d7 to collect bits flushed right
1989 movel d6
,d7 | use d6
-d7 to collect bits flushed right
1991 cmpw IMM
(1),d4 | if the exponent is less than
1 we
1993 cmpl IMM
(1),d4 | if the exponent is less than
1 we
1995 bge
2f | have to shift right
(denormalize
)
1998 addw IMM
(1),d4 | adjust the exponent
1999 lsrl IMM
(1),d0 | shift right once
2005 cmpw IMM
(1),d4 | is the exponent
1 already
?
2007 addl IMM
(1),d4 | adjust the exponent
2029 cmpl IMM
(1),d4 | is the exponent
1 already
?
2031 beq
2f | if
not loop back
2033 bra Ld$underflow | safety check
, shouldn
't execute '
2034 2: 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
2043 movew a1@
(6),d6 | rounding mode
in d6
2044 beq Lround$to$nearest
2046 cmpw IMM
(ROUND_TO_PLUS
),d6
2048 cmpl IMM
(ROUND_TO_PLUS
),d6
2054 | Here we have a correctly rounded result
(either normalized
or denormalized
).
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).
2062 cmpw IMM
(0x07ff),d4
2064 cmpl IMM
(0x07ff),d4
2067 | Now check for a denormalized number
(exponent
==0):
2071 | Put back the exponents
and sign
and return.
2073 lslw IMM
(4),d4 | exponent back to fourth
byte
2075 lsll IMM
(4),d4 | exponent back to fourth
byte
2077 bclr IMM
(DBL_MANT_DIG
-32-1),d0
2078 swap d0 |
and put back exponent
2085 orl d7
,d0 |
and sign also
2093 | XXX if frame pointer is ever removed
, stack pointer must
2099 |
=============================================================================
2101 |
=============================================================================
2103 | double __negdf2
(double
, double
);
2112 movew IMM
(NEGATE
),d5
2113 movel a6@
(8),d0 | get number to negate
in d0
-d1
2115 bchg IMM
(31),d0 | negate
2116 movel d0
,d2 | make a positive copy
(for the tests
)
2118 movel d2
,d4 | check for zero
2120 beq
2f | if zero
(either sign
) return
+zero
2121 cmpl IMM
(0x7ff00000),d2 | compare to
+INFINITY
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
2126 movel d0
,d7 | else get sign
and return INFINITY
2127 andl IMM
(0x80000000),d7
2129 1: lea SYM
(_fpCCR
),a0
2135 | XXX if frame pointer is ever removed
, stack pointer must
2143 |
=============================================================================
2145 |
=============================================================================
2151 |
int __cmpdf2
(double
, double
);
2155 moveml d2
-d7
,sp@
- | save registers
2160 movew IMM
(COMPARE
),d5
2161 movel a6@
(8),d0 | get first operand
2163 movel a6@
(16),d2 | get second operand
2165 | First check if a
and/or b are
(+/-) zero
and in that case clear
2167 movel d0
,d6 | copy signs
into d6
(a
) and d7
(b
)
2168 bclr IMM
(31),d0 |
and clear signs
in d0
and d2
2171 cmpl IMM
(0x7fff0000),d0 | check for a
== NaN
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
2178 cmpl IMM
(0x7fff0000),d2 | check for b
== NaN
2179 bhi Ld$inop | if d2
> 0x7ff00000, b is NaN
2180 beq Lcmpdf
$b$nf | if equal can be INFINITY
, so check d3
2188 | If the signs are
not equal check if a
>= 0
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
2193 | If the signs are equal check for
< 0
2196 | If both are negative exchange them
2209 | Now that they are positive we just compare them as longs
(does
this also
2210 | work for denormalized numbers
?).
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.
2216 bhi Lcmpdf
$b$
gt$a | |b|
> |a|
2217 bne Lcmpdf
$a$
gt$b | |b|
< |a|
2218 | If we got here a
== b.
2219 movel IMM
(EQUAL
),d0
2221 moveml
sp@
+,d2
-d7 | put back the registers
2224 | XXX if frame pointer is ever removed
, stack pointer must
2230 movel IMM
(GREATER
),d0
2232 moveml
sp@
+,d2
-d7 | put back the registers
2235 | XXX if frame pointer is ever removed
, stack pointer must
2243 moveml
sp@
+,d2
-d7 | put back the registers
2246 | XXX if frame pointer is ever removed
, stack pointer must
2269 |
=============================================================================
2271 |
=============================================================================
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
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.
2284 | Check for denormalized
numbers:
2285 1: btst IMM
(DBL_MANT_DIG
-32),d0
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).
2291 cmpw IMM
(1),d4 | remember that the exponent is at least one
2293 cmpl IMM
(1),d4 | remember that the exponent is at least one
2295 beq
2f | an exponent of one means denormalized
2296 addl d3
,d3 | else shift
and adjust the exponent
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
?)
2312 btst IMM
(0),d1 | is delta
< 1?
2313 beq
2f | if so
, do
not do anything
2314 orl d2
,d3 | is delta
== 1?
2315 bne
1f | if so round to even
2317 andl IMM
(2),d3 | bit
1 is the last significant bit
2322 1: movel IMM
(1),d3 | else
add 1
2326 | Shift right once
(because we used bit #DBL_MANT_DIG
-32!).
2339 | Now check again bit #DBL_MANT_DIG
-32 (rounding could have produced a
2340 |
'fraction overflow' ...
).
2341 btst IMM
(DBL_MANT_DIG
-32),d0
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.
2358 btst IMM
(DBL_MANT_DIG
-32-1),d0
2368 #endif
/* L_double
*/
2373 .globl $_exception_handler
2375 QUIET_NaN
= 0xffffffff
2376 SIGNL_NaN
= 0x7f800001
2377 INFINITY
= 0x7f800000
2381 FLT_MAX_EXP
= F_MAX_EXP
- F_BIAS
2382 FLT_MIN_EXP
= 1 - F_BIAS
2385 INEXACT_RESULT
= 0x0001
2388 DIVIDE_BY_ZERO
= 0x0008
2389 INVALID_OPERATION
= 0x0010
2403 ROUND_TO_NEAREST
= 0 | round result to nearest representable value
2404 ROUND_TO_ZERO
= 1 | round result towards zero
2405 ROUND_TO_PLUS
= 2 | round result towards plus infinity
2406 ROUND_TO_MINUS
= 3 | round result towards minus infinity
2410 .globl SYM
(__addsf3
)
2411 .globl SYM
(__subsf3
)
2412 .globl SYM
(__mulsf3
)
2413 .globl SYM
(__divsf3
)
2414 .globl SYM
(__negsf2
)
2415 .globl SYM
(__cmpsf2
)
2417 | These are common routines to return
and signal exceptions.
2423 | Return
and signal a denormalized number
2425 movew IMM
(INEXACT_RESULT
+UNDERFLOW
),d7
2426 moveq IMM
(SINGLE_FLOAT
),d6
2427 jmp $_exception_handler
2431 | Return a properly signed INFINITY
and set the exception flags
2432 movel IMM
(INFINITY
),d0
2434 movew IMM
(INEXACT_RESULT
+OVERFLOW
),d7
2435 moveq IMM
(SINGLE_FLOAT
),d6
2436 jmp $_exception_handler
2439 | Return
0 and set the exception flags
2441 movew IMM
(INEXACT_RESULT
+UNDERFLOW
),d7
2442 moveq IMM
(SINGLE_FLOAT
),d6
2443 jmp $_exception_handler
2446 | Return a quiet NaN
and set the exception flags
2447 movel IMM
(QUIET_NaN
),d0
2448 movew IMM
(INEXACT_RESULT
+INVALID_OPERATION
),d7
2449 moveq IMM
(SINGLE_FLOAT
),d6
2450 jmp $_exception_handler
2453 | Return a properly signed INFINITY
and set the exception flags
2454 movel IMM
(INFINITY
),d0
2456 movew IMM
(INEXACT_RESULT
+DIVIDE_BY_ZERO
),d7
2457 moveq IMM
(SINGLE_FLOAT
),d6
2458 jmp $_exception_handler
2460 |
=============================================================================
2461 |
=============================================================================
2462 | single precision routines
2463 |
=============================================================================
2464 |
=============================================================================
2466 | A single precision floating point number
(float
) has the
format:
2469 | unsigned int sign : 1; /* sign bit */
2470 | unsigned int exponent : 8; /* exponent, shifted by 126 */
2471 | unsigned int fraction : 23; /* fraction */
2474 | Thus sizeof
(float
) = 4 (32 bits
).
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
2480 |
=============================================================================
2482 |
=============================================================================
2484 | float __subsf3
(float
, float
);
2486 bchg IMM
(31),sp@
(8) | change sign of second operand
2488 |
=============================================================================
2490 |
=============================================================================
2492 | float __addsf3
(float
, float
);
2495 link a6
,IMM
(0) | everything will be done
in registers
2496 moveml d2
-d7
,sp@
- | save all data registers but d0
-d1
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
2510 movel d6
,a0 | save signs
in address registers
2511 movel d7
,a1 | so we can use d6
and d7
2513 | Get the exponents
and check for denormalized
and/or infinity.
2515 movel IMM
(0x00ffffff),d4 |
mask to get fraction
2516 movel IMM
(0x01000000),d5 |
mask to put hidden bit back
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
2525 swap d6 | put exponent
into first
word
2526 orl d5
,d0 |
and put hidden bit back
2528 | Now we have a
's exponent in d6 (second byte) and the mantissa in d0. '
2529 movel d1
,d7 | get exponent
in d7
2531 beq Laddsf
$b$den | branch if b is denormalized
2532 cmpl d4
,d7 | check for INFINITY
or NaN
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
2539 | Now we have b
's exponent in d7 (second byte) and the mantissa in d1. '
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
2545 movel d1
,d2 | move b to d2
, since we want to use
2546 | two registers to do the sum
2547 movel IMM
(0),d1 |
and clear the new ones
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
2555 cmpw d6
,d7 | compare exponents
2557 cmpl d6
,d7 | compare exponents
2559 beq Laddsf
$3 | if equal don
't shift '
2560 bhi
5f | branch if second exponent largest
2562 subl d6
,d7 | keep the largest exponent
2565 lsrw IMM
(8),d7 | put difference
in lower
byte
2567 lsrl IMM
(8),d7 | put difference
in lower
byte
2569 | if difference is too
large we don
't shift (actually, we can just exit) '
2571 cmpw IMM
(FLT_MANT_DIG
+2),d7
2573 cmpl IMM
(FLT_MANT_DIG
+2),d7
2577 cmpw IMM
(16),d7 | if difference
>= 16 swap
2579 cmpl IMM
(16),d7 | if difference
>= 16 swap
2590 lsrl IMM
(1),d2 | shift right second operand
2613 bne
2b | if still more bits
, go back to normal case
2617 exg d6
,d7 | exchange the exponents
2623 subl d6
,d7 | keep the largest exponent
2626 lsrw IMM
(8),d7 | put difference
in lower
byte
2628 lsrl IMM
(8),d7 | put difference
in lower
byte
2630 | if difference is too
large we don
't shift (and exit!) '
2632 cmpw IMM
(FLT_MANT_DIG
+2),d7
2634 cmpl IMM
(FLT_MANT_DIG
+2),d7
2638 cmpw IMM
(16),d7 | if difference
>= 16 swap
2640 cmpl IMM
(16),d7 | if difference
>= 16 swap
2651 lsrl IMM
(1),d0 | shift right first operand
2674 bne
6b | if still more bits
, go back to normal case
2675 | otherwise we fall through
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
).
2681 | Here we have to decide whether to
add or subtract the numbers
2683 exg d6
,a0 | get signs back
2684 exg d7
,a1 |
and save the exponents
2693 eorl d6
,d7 | combine sign bits
2694 bmi Lsubsf
$0 | if negative a
and b have opposite
2695 | sign so we actually subtract the
2698 | Here we have both positive
or both negative
2700 exg d6
,a0 | now we have the exponent
in d6
2706 movel a0
,d7 |
and sign
in d7
2707 andl IMM
(0x80000000),d7
2708 | Here we do the addition.
2711 |
Note: now we have d2
, d3
, d4
and d5 to play with
!
2713 | Put the exponent
, in the first
byte, in d2
, to use the
"standard" rounding
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
).
2724 | As
in the addition
(not in the subtraction
!) we could have set
2725 | one more bit we check
this:
2726 btst IMM
(FLT_MANT_DIG
+1),d0
2740 lea Laddsf
$4,a0 | to return from rounding routine
2741 lea SYM
(_fpCCR
),a1 | check the rounding mode
2745 movew a1@
(6),d6 | rounding mode
in d6
2746 beq Lround$to$nearest
2748 cmpw IMM
(ROUND_TO_PLUS
),d6
2750 cmpl IMM
(ROUND_TO_PLUS
),d6
2756 | Put back the exponent
, but check for overflow.
2763 bclr IMM
(FLT_MANT_DIG
-1),d0
2777 | We are here if a
> 0 and b
< 0 (sign bits cleared
).
2778 | Here we do the subtraction.
2779 movel d6
,d7 | put sign
in d7
2780 andl IMM
(0x80000000),d7
2782 subl d3
,d1 | result
in d0
-d1
2784 beq Laddsf$
ret | if zero just exit
2785 bpl
1f | if positive skip the following
2786 bchg IMM
(31),d7 | change sign bit
in d7
2791 exg d2
,a0 | now we have the exponent
in d2
2792 lsrw IMM
(8),d2 | put it
in the first
byte
2797 lsrl IMM
(8),d2 | put it
in the first
byte
2800 | Now d0
-d1 is positive
and the sign bit is
in d7.
2802 | Note that we do
not have to normalize
, since
in the subtraction bit
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
2810 movew a1@
(6),d6 | rounding mode
in d6
2811 beq Lround$to$nearest
2813 cmpw IMM
(ROUND_TO_PLUS
),d6
2815 cmpl IMM
(ROUND_TO_PLUS
),d6
2821 | Put back the exponent
(we can
't have overflow!). '
2822 bclr IMM
(FLT_MANT_DIG
-1),d0
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
).
2840 moveml
sp@
+,d2
-d7 | restore data registers
2843 | XXX if frame pointer is ever removed
, stack pointer must
2846 unlk a6 |
and return
2854 moveml
sp@
+,d2
-d7 | restore data registers
2857 | XXX if frame pointer is ever removed
, stack pointer must
2860 unlk a6 |
and return
2863 | If the numbers are denormalized remember to put exponent equal to
1.
2866 movel d5
,d6 | d5 contains
0x01000000
2873 notl d4 | make d4
into a
mask for the fraction
2874 |
(this was
not executed after the jump
)
2877 | The rest is mainly code for the different results which can be
2878 | returned
(checking always for
+/-INFINITY
and NaN
).
2881 | Return b
(if a is zero
).
2885 | Return a
(if b is zero
).
2889 | We have to check for NaN
and +/-infty.
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
2895 movel d0
,d0 | check for zero
(we do
this because we don
't '
2896 bne Laddsf$
ret | want to return
-0 by mistake
2897 bclr IMM
(31),d7 | if zero be sure to clear sign
2898 bra Laddsf$
ret | if everything OK just return
2900 | The value to be returned is either
+/-infty
or NaN
2901 andl IMM
(0x007fffff),d0 | check for NaN
2902 bne Lf$inop | if mantissa
not zero is NaN
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).
2910 orl d7
,d0 | put sign bit
2912 moveml
sp@
+,d2
-d7 | restore data registers
2915 | XXX if frame pointer is ever removed
, stack pointer must
2918 unlk a6 |
and return
2922 | Return a denormalized number
(for addition we don
't signal underflow) '
2923 lsrl IMM
(1),d0 | remember to shift right back once
2924 bra Laddsf$
ret |
and return
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
2928 |
not. When subtracting them
(i.e.
, when adding two numbers of
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.
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
)
2939 movel IMM
(INFINITY
),d4 | useful constant
(INFINITY
)
2940 movel d0
,d2 | save sign bits
2942 bclr IMM
(31),d0 | clear sign bits
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
)
2948 cmpl d4
,d1 | check now b
(d1
)
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
2952 | are adding
or subtracting them.
2953 eorl d3
,d2 | to check sign bits
2956 andl IMM
(0x80000000),d7 | get
(common
) sign bit
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
2962 cmpl d1
,d0 | are both infinite
?
2963 beq Lf$inop | if so return NaN
2966 andl IMM
(0x80000000),d7 | get a
's sign bit '
2967 cmpl d4
,d0 |
test now for infinity
2968 beq Lf$infty | if a is INFINITY return with
this sign
2969 bchg IMM
(31),d7 | else we know b is INFINITY
and has
2970 bra Lf$infty | the opposite sign
2972 |
=============================================================================
2974 |
=============================================================================
2976 | float __mulsf3
(float
, float
);
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
2989 andl IMM
(0x80000000),d7
2990 movel IMM
(INFINITY
),d6 | useful constant
(+INFINITY
)
2991 movel d6
,d5 | another
(mask for fraction
)
2993 movel IMM
(0x00800000),d4 |
this is to put hidden bit back
2994 bclr IMM
(31),d0 | get rid of a
's sign bit '
2996 beq Lmulsf
$a$0 | branch if a is zero
2997 bclr IMM
(31),d1 | get rid of b
's sign bit '
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
3031 addw d3
,d2 |
add exponents
3032 subw IMM
(F_BIAS
+1),d2 |
and subtract bias
(plus one
)
3034 addl d3
,d2 |
add exponents
3035 subl IMM
(F_BIAS
+1),d2 |
and subtract bias
(plus one
)
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.
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
3048 movel d4
,d1 | the sums will go
in d0
-d1
3051 | now bit FLT_MANT_DIG
-1 becomes bit
31:
3052 lsll IMM
(31-FLT_MANT_DIG
+1),d6
3054 | Start the
loop (we
loop #FLT_MANT_DIG times
):
3055 movew IMM
(FLT_MANT_DIG
-1),d3
3056 1: addl d1
,d1 | shift sum
3058 lsll IMM
(1),d6 | get bit bn
3059 bcc
2f | if
not set skip sum
3064 dbf d3
,1b |
loop back
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
).
3077 andw IMM
(0x03ff),d3
3078 andw IMM
(0xfd00),d1
3087 andl IMM
(0xfffffd00),d1
3098 movew IMM
(MULTIPLY
),d5
3100 btst IMM
(FLT_MANT_DIG
+1),d0
3117 movew IMM
(MULTIPLY
),d5
3121 movew IMM
(MULTIPLY
),d5
3125 movew IMM
(MULTIPLY
),d5
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
3132 | If either number is zero return zero
, unless the other is
+/-INFINITY
,
3133 |
or NaN
, in which case we return NaN.
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
3140 movel a6@
(12),d1 | get b again to check for non
-finiteness
3141 1: bclr IMM
(31),d1 | clear sign bit
3142 cmpl IMM
(INFINITY
),d1 |
and check for a
large exponent
3143 bge Lf$inop | if b is
+/-INFINITY
or NaN return NaN
3144 lea SYM
(_fpCCR
),a0 | else return zero
3150 | XXX if frame pointer is ever removed
, stack pointer must
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.
3163 1: addl d0
,d0 | shift a left
(until bit
23 is set
)
3165 subw IMM
(1),d2 |
and adjust exponent
3167 subql IMM
(1),d2 |
and adjust exponent
3169 btst IMM
(FLT_MANT_DIG
-1),d0
3171 bra
1b | else
loop back
3176 1: addl d1
,d1 | shift b left until bit
23 is set
3178 subw IMM
(1),d3 |
and adjust exponent
3180 subl IMM
(1),d3 |
and adjust exponent
3182 btst IMM
(FLT_MANT_DIG
-1),d1
3184 bra
1b | else
loop back
3186 |
=============================================================================
3188 |
=============================================================================
3190 | float __divsf3
(float
, float
);
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
3203 andl IMM
(0x80000000),d7 |
3204 movel IMM
(INFINITY
),d6 | useful constant
(+INFINITY
)
3205 movel d6
,d5 | another
(mask for fraction
)
3207 movel IMM
(0x00800000),d4 |
this is to put hidden bit back
3208 bclr IMM
(31),d0 | get rid of a
's sign bit '
3210 beq Ldivsf
$a$0 | branch if a is zero
3211 bclr IMM
(31),d1 | get rid of b
's sign bit '
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
3216 beq Ldivsf$inf | if a is INFINITY we have to check b
3217 cmpl d6
,d1 | now compare b with INFINITY
3218 bhi Ldivsf$inop | if b is NaN return NaN
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
3247 subw d3
,d2 | subtract exponents
3248 addw IMM
(F_BIAS
),d2 |
and add bias
3250 subl d3
,d2 | subtract exponents
3251 addl IMM
(F_BIAS
),d2 |
and add bias
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
3266 movew IMM
(FLT_MANT_DIG
+1),d3
3267 1: cmpl d0
,d1 | is a
< b
?
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
3272 2: addl d0
,d0 | multiply a by
2
3280 | Now we keep going to set the sticky bit ...
3281 movew IMM
(FLT_MANT_DIG
),d3
3295 subw IMM
(FLT_MANT_DIG
),d3
3298 subl IMM
(FLT_MANT_DIG
),d3
3303 movel d6
,d0 | put the ratio
in d0
-d1
3304 movel a0
,d7 | get sign back
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.
3309 btst IMM
(FLT_MANT_DIG
+1),d0
3310 beq
1f | if it is
not set
, then bit
24 is set
3318 | Now round
, check for over
- and underflow
, and exit.
3319 movew IMM
(DIVIDE
),d5
3323 movew IMM
(DIVIDE
),d5
3327 movew IMM
(DIVIDE
),d5
3331 movew IMM
(DIVIDE
),d5
3335 movew IMM
(DIVIDE
),d5
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
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
3343 movel IMM
(0),d0 | else return zero
3344 lea SYM
(_fpCCR
),a0 |
3350 | XXX if frame pointer is ever removed
, stack pointer must
3357 movew IMM
(DIVIDE
),d5
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
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
3366 movew IMM
(DIVIDE
),d5
3367 | If a is INFINITY we have to check b
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
3372 | If a number is denormalized we put an exponent of
1 but do
not put the
3373 | bit back
into the fraction.
3377 1: addl d0
,d0 | shift a left until bit FLT_MANT_DIG
-1 is set
3379 subw IMM
(1),d2 |
and adjust exponent
3381 subl IMM
(1),d2 |
and adjust exponent
3383 btst IMM
(FLT_MANT_DIG
-1),d0
3390 1: addl d1
,d1 | shift b left until bit FLT_MANT_DIG is set
3392 subw IMM
(1),d3 |
and adjust exponent
3394 subl IMM
(1),d3 |
and adjust exponent
3396 btst IMM
(FLT_MANT_DIG
-1),d1
3401 |
This is a common exit point for __mulsf3
and __divsf3.
3403 | First check for underlow
in the
exponent:
3405 cmpw IMM
(-FLT_MANT_DIG
-1),d2
3407 cmpl IMM
(-FLT_MANT_DIG
-1),d2
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
).
3414 movel IMM
(0),d6 | d6 is used temporarily
3416 cmpw IMM
(1),d2 | if the exponent is less than
1 we
3418 cmpl IMM
(1),d2 | if the exponent is less than
1 we
3420 bge
2f | have to shift right
(denormalize
)
3423 addw IMM
(1),d2 | adjust the exponent
3424 lsrl IMM
(1),d0 | shift right once
3426 roxrl IMM
(1),d6 | d6 collect bits we would lose otherwise
3427 cmpw IMM
(1),d2 | is the exponent
1 already
?
3429 addql IMM
(1),d2 | adjust the exponent
3439 cmpl IMM
(1),d2 | is the exponent
1 already
?
3441 beq
2f | if
not loop back
3443 bra Lf$underflow | safety check
, shouldn
't execute '
3444 2: 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
3452 movew a1@
(6),d6 | rounding mode
in d6
3453 beq Lround$to$nearest
3455 cmpw IMM
(ROUND_TO_PLUS
),d6
3457 cmpl IMM
(ROUND_TO_PLUS
),d6
3463 | Here we have a correctly rounded result
(either normalized
or denormalized
).
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).
3471 cmpw IMM
(0x00ff),d2
3473 cmpl IMM
(0x00ff),d2
3476 | Now check for a denormalized number
(exponent
==0).
3480 | Put back the exponents
and sign
and return.
3482 lslw IMM
(7),d2 | exponent back to fourth
byte
3484 lsll IMM
(7),d2 | exponent back to fourth
byte
3486 bclr IMM
(FLT_MANT_DIG
-1),d0
3487 swap d0 |
and put back exponent
3494 orl d7
,d0 |
and sign also
3502 | XXX if frame pointer is ever removed
, stack pointer must
3508 |
=============================================================================
3510 |
=============================================================================
3512 |
This is trivial
and could be shorter if we didn
't bother checking for NaN '
3515 | float __negsf2
(float
);
3524 movew IMM
(NEGATE
),d5
3525 movel a6@
(8),d0 | get number to negate
in d0
3526 bchg IMM
(31),d0 | negate
3527 movel d0
,d1 | make a positive copy
3529 tstl d1 | check for zero
3530 beq
2f | if zero
(either sign
) return
+zero
3531 cmpl IMM
(INFINITY
),d1 | compare to
+INFINITY
3533 bhi Lf$inop | if larger
(fraction
not zero
) is NaN
3534 movel d0
,d7 | else get sign
and return INFINITY
3535 andl IMM
(0x80000000),d7
3537 1: lea SYM
(_fpCCR
),a0
3543 | XXX if frame pointer is ever removed
, stack pointer must
3551 |
=============================================================================
3553 |
=============================================================================
3559 |
int __cmpsf2
(float
, float
);
3563 moveml d2
-d7
,sp@
- | save registers
3568 movew IMM
(COMPARE
),d5
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
3575 andl IMM
(0x7fffffff),d0
3577 cmpl IMM
(0x7f800000),d0
3581 andl IMM
(0x7fffffff),d1
3583 cmpl IMM
(0x7f800000),d1
3589 | If the signs are
not equal check if a
>= 0
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
3594 | If the signs are equal check for
< 0
3597 | If both are negative exchange them
3606 | Now that they are positive we just compare them as longs
(does
this also
3607 | work for denormalized numbers
?).
3609 bhi Lcmpsf
$b$
gt$a | |b|
> |a|
3610 bne Lcmpsf
$a$
gt$b | |b|
< |a|
3611 | If we got here a
== b.
3612 movel IMM
(EQUAL
),d0
3614 moveml
sp@
+,d2
-d7 | put back the registers
3621 movel IMM
(GREATER
),d0
3623 moveml
sp@
+,d2
-d7 | put back the registers
3626 | XXX if frame pointer is ever removed
, stack pointer must
3634 moveml
sp@
+,d2
-d7 | put back the registers
3637 | XXX if frame pointer is ever removed
, stack pointer must
3650 |
=============================================================================
3652 |
=============================================================================
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
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.
3665 | Check for denormalized
numbers:
3666 1: btst IMM
(FLT_MANT_DIG
),d0
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).
3672 cmpw IMM
(1),d2 | remember that the exponent is at least one
3674 cmpl IMM
(1),d2 | remember that the exponent is at least one
3676 beq
2f | an exponent of one means denormalized
3677 addl d1
,d1 | else shift
and adjust the exponent
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
?)
3691 btst IMM
(0),d0 | is delta
< 1?
3692 beq
2f | if so
, do
not do anything
3693 tstl d1 | is delta
== 1?
3694 bne
1f | if so round to even
3696 andl IMM
(2),d1 | bit
1 is the last significant bit
3699 1: movel IMM
(1),d1 | else
add 1
3701 | Shift right once
(because we used bit #FLT_MANT_DIG
!).
3703 | Now check again bit #FLT_MANT_DIG
(rounding could have produced a
3704 |
'fraction overflow' ...
).
3705 btst IMM
(FLT_MANT_DIG
),d0
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.
3716 btst IMM
(FLT_MANT_DIG
-1),d0
3726 #endif
/* L_float
*/
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.
3738 .globl SYM
(__eqdf2
)
3748 #endif
/* L_eqdf2
*/
3753 .globl SYM
(__nedf2
)
3763 #endif
/* L_nedf2
*/
3768 .globl SYM
(__gtdf2
)
3778 #endif
/* L_gtdf2
*/
3783 .globl SYM
(__gedf2
)
3793 #endif
/* L_gedf2
*/
3798 .globl SYM
(__ltdf2
)
3808 #endif
/* L_ltdf2
*/
3813 .globl SYM
(__ledf2
)
3823 #endif
/* L_ledf2
*/
3825 | The comments above about __eqdf2
, et.
al.
, also apply to __eqsf2
,
3826 | et.
al.
, except that the latter
call __cmpsf2 rather than __cmpdf2.
3831 .globl SYM
(__eqsf2
)
3839 #endif
/* L_eqsf2
*/
3844 .globl SYM
(__nesf2
)
3852 #endif
/* L_nesf2
*/
3857 .globl SYM
(__gtsf2
)
3865 #endif
/* L_gtsf2
*/
3870 .globl SYM
(__gesf2
)
3878 #endif
/* L_gesf2
*/
3883 .globl SYM
(__ltsf2
)
3891 #endif
/* L_ltsf2
*/
3896 .globl SYM
(__lesf2
)
3904 #endif
/* L_lesf2
*/