- Removed unused HandleEvent method.
[AROS.git] / arch / m68k-all / libgcc1 / _addsubdf3.s
blob409c801aa02695c8dc6b42ddac54f0422bcb875c
1 | double floating point add/subtract routine
3 | written by Kai-Uwe Bloem (I5110401@dbstu1.bitnet).
4 | Based on a 80x86 floating point packet from comp.os.minix, written by P.Housel
7 | Revision 1.3, kub 01-90 :
8 | added support for denormalized numbers
10 | Revision 1.2, kub 01-90 :
11 | replace far shifts by swaps to gain speed
13 | Revision 1.1, kub 12-89 :
14 | Ported over to 68k assembler
16 | Revision 1.0:
17 | original 8088 code from P.S.Housel
19 .text
20 .even
21 .globl __subdf3
22 .globl __adddf3
24 __subdf3:
25 eorb #0x80,%sp@(12) | reverse sign of v
26 __adddf3:
27 lea %sp@(4),%a0 | pointer to u and v parameter
28 moveml %d2-%d7,%sp@- | save registers
29 moveml %a0@,%d4-%d5/%d6-%d7 | %d4-%d5 = v, %d6-%d7 = u
31 movel %d6,%d0 | %d0 = u.exp
32 swap %d0
33 movel %d6,%d2 | %d2.h = u.sign
34 movew %d0,%d2
35 lsrw #4,%d0
36 andw #0x07ff,%d0 | kill sign bit
38 movel %d4,%d1 | %d1 = v.exp
39 swap %d1
40 eorw %d1,%d2 | %d2.l = u.sign ^ v.sign
41 lsrw #4,%d1
42 andw #0x07ff,%d1 | kill sign bit
44 andl #0x0fffff,%d6 | remove exponent from u.mantissa
45 tstw %d0 | check for zero exponent - no leading "1"
46 beq L_00
47 orl #0x100000,%d6 | restore implied leading "1"
48 bra L_10
49 L_00: addw #1,%d0 | "normalize" exponent
50 L_10:
51 andl #0x0fffff,%d4 | remove exponent from v.mantissa
52 tstw %d1 | check for zero exponent - no leading "1"
53 beq L_01
54 orl #0x100000,%d4 | restore implied leading "1"
55 bra L_11
56 L_01: addw #1,%d1 | "normalize" exponent
57 L_11:
58 clrw %d3 | (put initial zero rounding bits in %d3)
59 negw %d1 | %d1 = u.exp - v.exp
60 addw %d0,%d1
61 beq L_5 | exponents are equal - no shifting neccessary
62 bgt L_12 | not equal but no exchange neccessary
63 exg %d4,%d6 | exchange u and v
64 exg %d5,%d7
65 subw %d1,%d0 | %d0 = u.exp - (u.exp - v.exp) = v.exp
66 negw %d1
67 tstw %d2 | %d2.h = u.sign ^ (u.sign ^ v.sign) = v.sign
68 bpl L_12
69 bchg #31,%d2
70 L_12:
71 cmpw #53,%d1 | is u so much bigger that v is not
72 bge L_7 | significant ?
74 movew #10-1,%d3 | shift u left up to 10 bits to minimize loss
75 L_2:
76 addl %d7,%d7
77 addxl %d6,%d6
78 subw #1,%d0 | decrement exponent
79 subw #1,%d1 | done shifting altogether ?
80 dbeq %d3,L_2 | loop if still can shift u.mant more
81 clrw %d3
82 L_3:
83 cmpw #16,%d1 | see if fast rotate possible
84 blt L_4
85 orb %d5,%d3 | set rounding bits
86 orb %d2,%d3
87 sne %d2 | "sticky byte"
88 movew %d5,%d3
89 lsrw #8,%d3
90 movew %d4,%d5 | rotate by swapping register halfs
91 swap %d5
92 clrw %d4
93 swap %d4
94 subw #16,%d1
95 bra L_3
96 L_0:
97 lsrl #1,%d4 | shift v.mant right the rest of the way
98 roxrl #1,%d5 | to line it up with u.mant
99 orb %d3,%d2 | set "sticky byte" if necessary
100 roxrw #1,%d3 | shift into rounding bits
101 L_4: dbra %d1,L_0 | loop
102 andb #1,%d2 | see if "sticky bit" should be set
103 orb %d2,%d3
104 L_5:
105 tstw %d2 | are the signs equal ?
106 bpl L_6 | yes, no negate necessary
108 negb %d3 | negate rounding bits and v.mant
109 negl %d5
110 negxl %d4
111 L_6:
112 addl %d5,%d7 | u.mant = u.mant + v.mant
113 addxl %d4,%d6
114 bcs L_7 | needn't negate
115 tstw %d2 | opposite signs ?
116 bpl L_7 | don't need to negate result
118 negb %d3 | negate rounding bits and u.mant
119 negl %d7
120 negxl %d6
121 notl %d2 | switch sign
122 L_7:
123 movel %d6,%d4 | move result for normalization
124 movel %d7,%d5
125 moveb %d3,%d1 | put rounding bits in %d1 for norm_df
126 swap %d2 | put sign into %d2 (exponent is in %d0)
127 jmp norm_df | leave registers on stack for norm_df