home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
files
/
mint
/
mntlib18
/
_divdf3.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-03
|
5KB
|
252 lines
#if !defined (__M68881__) && !defined (sfp004)
| double floating point divide 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.2, kub 01-90 :
| added support for denormalized numbers
|
| Revision 1.1, kub 12-89 :
| Ported over to 68k assembler
|
| Revision 1.0:
| original 8088 code from P.S.Housel
BIAS8 = 0x3FF-1
.text
.even
.globl __divdf3, ___divdf3
.globl __infinitydf
# ifdef ERROR_CHECK
LC0:
.ascii "floating point division by 0\12\15\0"
.even
# endif ERROR_CHECK
__divdf3:
___divdf3:
# ifdef ERROR_CHECK
tstl a7@(12) | check if divisor is 0
bne continue
tstl a7@(16)
bne continue
moveml d0-d1,a7@-
pea LC0
pea __iob+52 |
jbsr _fprintf |
addql #8,a7 |
moveml a7@+,d0-d1
| set _errno to ERANGE
# ifdef __MSHORT__
movew #63,_errno
# else
movel #63,_errno
# endif
movel #0x7ff00000,d0 | return signed infinity
clrl d1 |
btst #31,a7@(4) | transfer sign of dividend
beq clear | (mjr++)
bset #31,d0 |
rts |
clear: |
bclr #31,d0 |
rts
continue:
# endif ERROR_CHECK
lea sp@(4),a0 | pointer to parameters u and v
moveml d2-d7,sp@- | save registers
moveml a0@,d4-d5/d6-d7 | d4-d5 = u, d6-d7 = v
movel d4,d0 | d0 = u.exp
swap d0
movew d0,d2 | d2 = u.sign
lsrw #4,d0
andw #0x07ff,d0 | kill sign bit
movel d6,d1 | d1 = v.exp
swap d1
eorw d1,d2 | d2 = u.sign ^ v.sign (in bit 31)
lsrw #4,d1
andw #0x07ff,d1 | kill sign bit
andl #0x0fffff,d4 | remove exponent from u.mantissa
tstw d0 | check for zero exponent - no leading "1"
beq 0f
orl #0x100000,d4 | restore implied leading "1"
bra 1f
0: addw #1,d0 | "normalize" exponent
1: movel d4,d3
orl d5,d3
beq retz | dividing zero
andl #0x0fffff,d6 | remove exponent from v.mantissa
tstw d1 | check for zero exponent - no leading "1"
beq 0f
orl #0x100000,d6 | restore implied leading "1"
bra 1f
0: addw #1,d1 | "normalize" exponent
1: movel d6,d3
orl d7,d3
#ifndef ERROR_CHECK
beq divz | divide by zero
#endif ERROR_CHECK
movew d2,a0 | save sign
subw d1,d0 | subtract exponents,
addw #BIAS8-11+1,d0 | add bias back in, account for shift
addw #66,d0 | add loop offset, +2 for extra rounding bits
| for denormalized numbers (2 implied by dbra)
movew #24,d1 | bit number for "implied" pos (+4 for rounding)
movel #-1,d2 | zero the quotient
movel #-1,d3 | (for speed it is a one''s complement)
subl d7,d5 | initial subtraction,
subxl d6,d4 | u = u - v
2:
btst d1,d2 | divide until 1 in implied position
beq 5f
addl d5,d5
addxl d4,d4
bcs 4f | if carry is set, add, else subtract
addxl d3,d3 | shift quotient and set bit zero
addxl d2,d2
subl d7,d5 | subtract
subxl d6,d4 | u = u - v
dbra d0,2b | give up if result is denormalized
bra 5f
4:
addxl d3,d3 | shift quotient and clear bit zero
addxl d2,d2
addl d7,d5 | add (restore)
addxl d6,d4 | u = u + v
dbra d0,2b | give up if result is denormalized
5: subw #2,d0 | remove rounding offset for denormalized nums
notl d2 | invert quotient to get it right
notl d3
movel d2,d4 | save quotient mantissa
movel d3,d5
movew a0,d2 | get sign back
clrw d1 | zero rounding bits
jmp norm_df | (registers on stack removed by norm_df)
retz: clrl d0 | zero destination
clrl d1
moveml sp@+,d2-d7
rts | no normalization needed
#ifndef ERROR_CHECK
divz: moveml __infinitydf,d0-d1 | return infinty value
moveml sp@+,d2-d7 | should really cause trap ?!?
btst #31,a7@(4) | transfer sign of dividend
beq clear | (mjr++)
bset #31,d0 |
rts |
clear: |
bclr #31,d0 |
rts
#endif ERROR_CHECK
#endif
#ifdef sfp004
| double precision floating point stuff for Atari-gcc using the SFP004
| developed with gas
|
| double precision division
|
| M. Ritzert (mjr at dmzrzu71)
|
| 4.10.1990
|
| no NAN checking implemented to gain compatibility with the TT-lib
|
| addresses of the 68881 data port. This choice is fastest when much data is
| transferred between the two processors.
comm = -6
resp = -16
zahl = 0
| waiting loop ...
|
| wait:
| ww: cmpiw #0x8900,a0@(resp)
| beq ww
| is coded directly by
| .long 0x0c688900, 0xfff067f8
# ifdef ERROR_CHECK
LC0:
.ascii "floating point division by 0\12\15\0"
.even
# endif ERROR_CHECK
.text
.even
.globl __divdf3, ___divdf3
__divdf3:
___divdf3:
# ifdef ERROR_CHECK
tstl a7@(12) | check if divisor is 0
bne continue
tstl a7@(16)
bne continue
moveml d0-d7/a0-a6,a7@- | print error message
pea LC0
movew #9,a7@-
trap #1
addql #6,a7
moveml a7@+,d0-d7/a0-a6
| set _errno to ERANGE
# ifdef __MSHORT__
movew #63,_errno
# else
movel #63,_errno
# endif
movel #0x7ff00000,d0 | return signed infinity
clrl d1 |
btst #31,a7@(4) | transfer sign of dividend
beq clear | (mjr++)
bset #31,d0 |
rts |
clear: |
bclr #31,d0 |
rts
continue:
# endif ERROR_CHECK
lea 0xfffa50,a0
movew #0x5400,a0@(comm) | load first argument to fp0
cmpiw #0x8900,a0@(resp) | check
movel a7@(4),a0@
movel a7@(8),a0@
movew #0x5420,a0@(comm)
.long 0x0c688900, 0xfff067f8
movel a7@(12),a0@
movel a7@(16),a0@
movew #0x7400,a0@(comm) | result to d0
.long 0x0c688900, 0xfff067f8
movel a0@,d0
movel a0@,d1
rts
#endif sfp004