home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
zip
/
mint
/
mntlib16.lzh
/
MNTLIB16
/
NORMDF.CPP
< prev
next >
Wrap
Text File
|
1993-08-03
|
5KB
|
181 lines
| double floating point normalization routine
|
| written by Kai-Uwe Bloem (I5110401@dbstu1.bitnet).
| Based on a 80x86 floating point packet from comp.os.minix, written by P.Housel
|
| Revision 1.6, kub 04-90 :
| more robust handling exponent and sign handling for 32 bit integers. There
| are now overflow tests for 32 bit exponents, and bit 31 of the sign flag
| is or ed to bit 15 for later checks (i.e. both bits 31 and 15 are now sign
| bits). Take care, the upper 16 bits of rounding info are ignored for 32 bit
| integers !
|
| Revision 1.5, ++jrb 03-90:
| change __normdf interface to expect ints instead of shorts. easier
| to interface to 32 bit int code. this file is now pre-processed,
| with __MSHORT__ defined when ints are 16 bits.
|
| Revision 1.4, kub 03-90 :
| export ___normdf entry to C language. Rename the internal entry to a name
| not accessible from C to prevent crashes
|
| Revision 1.3, kub 01-90 :
| added support for denormalized numbers
|
| Revision 1.2, kub 01-90 :
| replace far shifts by swaps to gain speed
|
| Revision 1.1, kub 12-89 :
| Ported over to 68k assembler
|
| Revision 1.0:
| original 8088 code from P.S.Housel
.text
.even
.globl __infinitydf
.globl ___normdf
.globl norm_df
| C entry, for procs dealing with the internal representation :
| double __normdf(long long mant, int exp, int sign, int rbits);
___normdf:
lea sp@(4),a0 | parameter pointer
moveml d2-d7,sp@- | save working registers
moveml a0@+,d4-d5 | get mantissa
#ifdef __MSHORT__
movew a0@+,d0 | get exponent
movew a0@+,d2 | get sign
movew a0@+,d1 | rounding information
#else
movel a0@+,d0 | get exponent
movel a0@+,d2 | get sign
bpl 0f | or bit 31 to bit 15 for later tests
orw #0x8000,d2
0: movel a0@+,d1 | rounding information
cmpl #0x7fff,d0 | test exponent
bgt oflow
cmpl #-0x8000,d0
blt retz
#endif
| internal entry for floating point package, saves time
| d0=u.exp, d2=u.sign, d1=rounding bits, d4/d5=mantissa
| registers d2-d7 must be saved on the stack !
norm_df:
movel d4,d3 | rounding and u.mant == 0 ?
orl d5,d3
bne 1f
tstb d1
beq retz
1:
movel d4,d3
andl #0xfffff000,d3 | fast shift, 16 bits ?
bne 2f
cmpw #9,d0 | shift is going to far; do normal shift
ble 2f | (minimize shifts here : 10l = 16l + 6r)
swap d4 | yes, swap register halfs
swap d5
movew d5,d4
moveb d1,d5 | some doubt about this one !
lslw #8,d5
clrw d1
subw #16,d0 | account for swap
bra 1b
2:
clrb d2 | sticky byte
movel #0xffe00000,d6
3: tstw d0 | divide (shift)
ble 0f | denormalized number
movel d4,d3
andl d6,d3 | or until no bits above 53
beq 4f
0: addw #1,d0 | increment exponent
lsrl #1,d4
roxrl #1,d5
orb d1,d2 | set sticky
roxrb #1,d1 | shift into rounding bits
bra 3b
4:
andb #1,d2
orb d2,d1 | make least sig bit sticky
movel #0xfff00000,d6
5: movel d4,d3 | multiply (shift) until
andl d6,d3 | one in implied position
bne 6f
subw #1,d0 | decrement exponent
beq 6f | too small. store as denormalized number
addb d1,d1 | some doubt about this one *
addxl d5,d5
addxl d4,d4
bra 5b
6:
tstb d1 | check rounding bits
bge 8f | round down - no action neccessary
negb d1
bvc 7f | round up
bclr #0,d5 | tie case - round to even
bra 8f
7:
clrl d1 | zero rounding bits
addl #1,d5
addxl d1,d4
tstw d0
bne 0f | renormalize if number was denormalized
addw #1,d0 | correct exponent for denormalized numbers
bra 2b
0: movel d4,d3 | check for rounding overflow
andl #0xffe00000,d3
bne 2b | go back and renormalize
8:
movel d4,d3 | check if normalization caused an underflow
orl d5,d3
beq retz
cmpw #0,d0 | check for exponent overflow or underflow
blt retz
cmpw #2047,d0
bge oflow
lslw #4,d0 | re-position exponent
andw #0x8000,d2 | sign bit
orw d2,d0
swap d0 | map to upper word
clrw d0
andl #0x0fffff,d4 | top mantissa bits
orl d0,d4 | insert exponent and sign
movel d4,d0
movel d5,d1
moveml sp@+,d2-d7
rts
.globl _errno | from <errno.h>
ERANGE = 34
retz:
#ifdef __MSHORT__
movew #ERANGE,_errno | set errno
#else
movel #ERANGE,_errno | set errno
#endif
clrl d0 | return zero value
clrl d1
moveml sp@+,d2-d7
rts
oflow:
#ifdef __MSHORT__
movew #ERANGE,_errno | set errno
#else
movel #ERANGE,_errno | set errno
#endif
moveml __infinitydf,d0-d1 | return infinty value
andw #0x8000,d2 | get sign bit of argument
swap d2
clrw d2
orl d2,d0
moveml sp@+,d2-d7 | should really cause trap ?!?
rts
__infinitydf: | +infinity as proposed by IEEE
.long 0x7ff00000,0x00000000