- Removed unnecessary casts.
[AROS.git] / arch / m68k-all / libgcc1 / _normdf.s
blobd4e16694657a0178590b9a51ef191e0f6e5584f2
1 | double floating point normalization 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
6 | Revision 1.6, kub 04-90 :
7 | more robust handling exponent and sign handling for 32 bit integers. There
8 | are now overflow tests for 32 bit exponents, and bit 31 of the sign flag
9 | is or ed to bit 15 for later checks (i.e. both bits 31 and 15 are now sign
10 | bits). Take care, the upper 16 bits of rounding info are ignored for 32 bit
11 | integers !
13 | Revision 1.5, ++jrb 03-90:
14 | change _normdf interface to expect ints instead of shorts. easier
15 | to interface to 32 bit int code. this file is now pre-processed,
16 | with ___MSHORT___ defined when ints are 16 bits.
18 | Revision 1.4, kub 03-90 :
19 | export ___normdf entry to C language. Rename the internal entry to a name
20 | not accessible from C to prevent crashes
22 | Revision 1.3, kub 01-90 :
23 | added support for denormalized numbers
25 | Revision 1.2, kub 01-90 :
26 | replace far shifts by swaps to gain speed
28 | Revision 1.1, kub 12-89 :
29 | Ported over to 68k assembler
31 | Revision 1.0:
32 | original 8088 code from P.S.Housel
34 .text
35 .even
36 .globl _infinitydf
37 .globl __normdf
38 .globl norm_df
40 | C entry, for procs dealing with the internal representation :
41 | double _normdf(long long mant, int exp, int sign, int rbits);
42 __normdf:
43 lea %sp@(4),%a0 | parameter pointer
44 moveml %d2-%d7,%sp@- | save working registers
45 moveml %a0@+,%d4-%d5 | get mantissa
46 #ifdef ___MSHORT___
47 movew %a0@+,%d0 | get exponent
48 movew %a0@+,%d2 | get sign
49 movew %a0@+,%d1 | rounding information
50 #else
51 movel %a0@+,%d0 | get exponent
52 movel %a0@+,%d2 | get sign
53 bpl L_00 | or bit 31 to bit 15 for later tests
54 orw #0x8000,%d2
55 L_00: movel %a0@+,%d1 | rounding information
57 cmpl #0x7fff,%d0 | test exponent
58 bgt oflow
59 cmpl #-0x8000,%d0
60 blt eretz
61 #endif
62 | internal entry for floating point package, saves time
63 | %d0=u.exp, %d2=u.sign, %d1=rounding bits, %d4/%d5=mantissa
64 | registers %d2-%d7 must be saved on the stack !
65 norm_df:
66 movel %d4,%d3 | rounding and u.mant == 0 ?
67 orl %d5,%d3
68 bne L_10
69 tstb %d1
70 beq retz
71 L_10:
72 movel %d4,%d3
73 andl #0xfffff000,%d3 | fast shift, 16 bits ?
74 bne L_2
75 cmpw #9,%d0 | shift is going to far; do normal shift
76 ble L_2 | (minimize shifts here : 10l = 16l + 6r)
77 swap %d4 | yes, swap register halfs
78 swap %d5
79 movew %d5,%d4
80 moveb %d1,%d5 | some doubt about this one !
81 lslw #8,%d5
82 clrw %d1
83 subw #16,%d0 | account for swap
84 bra L_10
85 L_2:
86 clrb %d2 | sticky byte
87 movel #0xffe00000,%d6
88 L_3: tstw %d0 | divide (shift)
89 ble L_01 | denormalized number
90 movel %d4,%d3
91 andl %d6,%d3 | or until no bits above 53
92 beq L_4
93 L_01: addw #1,%d0 | increment exponent
94 lsrl #1,%d4
95 roxrl #1,%d5
96 orb %d1,%d2 | set sticky
97 roxrb #1,%d1 | shift into rounding bits
98 bra L_3
99 L_4:
100 andb #1,%d2
101 orb %d2,%d1 | make least sig bit sticky
102 movel #0xfff00000,%d6
103 L_5: movel %d4,%d3 | multiply (shift) until
104 andl %d6,%d3 | one in implied position
105 bne L_6
106 subw #1,%d0 | decrement exponent
107 beq L_6 | too small. store as denormalized number
108 addb %d1,%d1 | some doubt about this one *
109 addxl %d5,%d5
110 addxl %d4,%d4
111 bra L_5
112 L_6:
113 tstb %d1 | check rounding bits
114 bge L_8 | round down - no action neccessary
115 negb %d1
116 bvc L_7 | round up
117 bclr #0,%d5 | tie case - round to even
118 bra L_8
119 L_7:
120 clrl %d1 | zero rounding bits
121 addl #1,%d5
122 addxl %d1,%d4
123 tstw %d0
124 bne L_02 | renormalize if number was denormalized
125 addw #1,%d0 | correct exponent for denormalized numbers
126 bra L_2
127 L_02: movel %d4,%d3 | check for rounding overflow
128 andl #0xffe00000,%d3
129 bne L_2 | go back and renormalize
130 L_8:
131 movel %d4,%d3 | check if normalization caused an underflow
132 orl %d5,%d3
133 beq eretz
134 cmpw #0,%d0 | check for exponent overflow or underflow
135 blt eretz
136 cmpw #2047,%d0
137 bge oflow
139 lslw #4,%d0 | re-position exponent
140 andw #0x8000,%d2 | sign bit
141 orw %d2,%d0
142 swap %d0 | map to upper word
143 clrw %d0
144 andl #0x0fffff,%d4 | top mantissa bits
145 orl %d0,%d4 | insert exponent and sign
146 movel %d4,%d0
147 movel %d5,%d1
148 moveml %sp@+,%d2-%d7
151 |#ifdef WITH_ERRNO
152 | .globl _errno | from <errno.h>
153 |ERANGE = 34
154 |#endif
156 eretz:
157 |#ifdef WITH_ERRNO
158 |#ifdef ___MSHORT___
159 | movew #ERANGE,_errno | set errno
160 |#else
161 | movel #ERANGE,_errno | set errno
162 |#endif
163 |#endif
164 retz:
165 clrl %d0 | return zero value
166 clrl %d1
167 moveml %sp@+,%d2-%d7
170 oflow:
171 |#ifdef WITH_ERRNO
172 |#ifdef ___MSHORT___
173 | movew #ERANGE,_errno | set errno
174 |#else
175 | movel #ERANGE,_errno | set errno
176 |#endif
177 |#endif
178 moveml _infinitydf,%d0-%d1 | return infinty value
179 andw #0x8000,%d2 | get sign bit of argument
180 swap %d2
181 clrw %d2
182 orl %d2,%d0
183 moveml %sp@+,%d2-%d7 | should really cause trap ?!?
186 _infinitydf: | +infinity as proposed by IEEE
187 .long 0x7ff00000,0x00000000