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
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
32 | original
8088 code from P.S.Housel
40 | C entry
, for procs dealing with the internal representation
:
41 | double _normdf
(long long mant
, int exp
, int sign
, int rbits
);
43 lea
%sp@
(4),%a0 | parameter pointer
44 moveml
%d2-
%d7
,%sp@
- | save working registers
45 moveml
%a0@
+,%d4-
%d5 | get mantissa
47 movew
%a0@
+,%d0 | get exponent
48 movew
%a0@
+,%d2 | get sign
49 movew
%a0@
+,%d1 | rounding information
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
55 L_00
: movel
%a0@
+,%d1 | rounding information
57 cmpl #0x7fff,%d0 | test exponent
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
!
66 movel
%d4
,%d3 | rounding
and u.mant
== 0 ?
73 andl
#0xfffff000,%d3 | fast shift, 16 bits ?
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
80 moveb
%d1
,%d5 | some doubt about this one
!
83 subw
#16,%d0 | account for swap
86 clrb
%d2 | sticky byte
88 L_3
: tstw
%d0 | divide
(shift
)
89 ble L_01 | denormalized number
91 andl
%d6
,%d3 |
or until no bits above
53
93 L_01
: addw
#1,%d0 | increment exponent
96 orb
%d1
,%d2 | set sticky
97 roxrb
#1,%d1 | shift into rounding bits
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
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
*
113 tstb
%d1 | check rounding bits
114 bge L_8 | round down
- no action neccessary
117 bclr #0,%d5 | tie case - round to even
120 clrl
%d1 | zero rounding bits
124 bne L_02 | renormalize if number was denormalized
125 addw
#1,%d0 | correct exponent for denormalized numbers
127 L_02
: movel
%d4
,%d3 | check for rounding overflow
129 bne L_2 | go back
and renormalize
131 movel
%d4
,%d3 | check if normalization caused an underflow
134 cmpw #0,%d0 | check for exponent overflow or underflow
139 lslw
#4,%d0 | re-position exponent
140 andw
#0x8000,%d2 | sign bit
142 swap
%d0 | map to upper word
144 andl
#0x0fffff,%d4 | top mantissa bits
145 orl
%d0
,%d4 | insert exponent
and sign
152 |
.globl _errno | from <errno.h>
159 | movew
#ERANGE,_errno | set errno
161 | movel
#ERANGE,_errno | set errno
165 clrl
%d0 | return zero value
173 | movew
#ERANGE,_errno | set errno
175 | movel
#ERANGE,_errno | set errno
178 moveml _infinitydf
,%d0-
%d1 | return infinty value
179 andw
#0x8000,%d2 | get sign bit of argument
183 moveml
%sp@
+,%d2-
%d7 | should really cause
trap ?
!?
186 _infinitydf
: |
+infinity as proposed by IEEE
187 .long 0x7ff00000,0x00000000