home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
GEMini Atari
/
GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso
/
files
/
mint
/
mntlib18
/
ldexp.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1993-08-03
|
6KB
|
278 lines
#if !defined (__M68881__) && !defined (sfp004)
| add exponent to floating point number
| C Interface
| double ldexp(double value, unsigned int exp);
| returns value * 2**exp
| (int is 16 bits if -mshort, 32 bits if !-mshort)
|-----------------------------------------------------------------------------
| ported to 68000 by Kai-Uwe Bloem, 12/89
| #1 original author: Peter S. Housel 9/21/88,01/17/89,03/19/89,5/24/89
| #2 added support for denormalized numbers -kub-, 01/90
| #3 ported to gcc ++jrb 04/90
| #4 handle exponent overflow when ints are 32 bits -kub-, 04/90
|-----------------------------------------------------------------------------
.text; .even
.globl _ldexp
.globl __infinitydf
#ifdef ERROR_CHECK
_Overflow:
.ascii "ldexp: OVERFLOW\12\15\0"
.even
#endif ERROR_CHECK
_ldexp:
lea sp@(4),a1
moveml d2-d7,sp@- | save d2-d7
movew a1@,d0 | extract value.exp
movew d0,d2 | extract value.sign
lsrw #4,d0
andw #0x7ff,d0 | kill sign bit
andw #0x0f,a1@ | remove exponent from value.mantissa
tstw d0 | check for zero exponent - no leading 1
beq 0f
orw #0x10,a1@ | restore implied leading 1
bra 1f
0: addw #1,d0
1:
#ifdef __MSHORT__
addw a1@(8),d0 | add in exponent
extl d0
#else
extl d0
addl a1@(8),d0 | add in exponent
#endif
cmpl #-53,d0 | hmm. works only if 1 in implied position...
ble retz | range error - underflow
cmpl #2047,d0
bge rangerr | range error - overflow
clrw d1 | zero rounding bits
moveml a1@,d4-d5 | value into d4,d5
jmp norm_df | norm_df will pop d2-d7 and rts
.globl _errno | from <errno.h>
ERANGE = 63
retz:
moveq #0,d0 | zero return value
moveq #0,d1
jra L0
rangerr:
#ifdef ERROR_CHECK
# ifdef __MSHORT__
movew #ERANGE,_errno | set errno
# else
movel #ERANGE,_errno | set errno
# endif
moveml d0-d1,a7@-
pea _Overflow | for printf
pea __iob+52 |
jbsr _fprintf |
addql #8,a7 |
moveml a7@+,d0-d1
#endif ERROR_CHECK
moveml __infinitydf,d0-d1 | return HUGE_VAL (same as in <math.h>)
andw #0x8000,d2 | get sign bit of argument
swap d2
clrw d2
orl d2,d0
L0:
moveml sp@+,d2-d7 | pop saved reggies
rts
#else __M68881__ || sfp004
#ifdef __M68881__
|#######################################################################
|
|# add exponent to floating point number
|# C Interface
|# double ldexp(double value, unsigned int exp);
|# returns value * 2**exp
|# (int is 16 bits if -mshort, 32 bits if !-mshort)
|# performed entirely on the 68881 to avoid overfow as good as possible
|##############################################################################
|# hacked for the 68881 by Michael Ritzert, 5.10.90
|##############################################################################
|# ported fromt sfp004 to real coprocessor, mjr, August 1991
|################################################################################
.text; .even
.globl _ldexp
#ifdef ERROR_CHECK
_Domain:
.ascii "ldexp: NAN\12\15\0"
_Overflow:
.ascii "ldexp: OVERFLOW\12\15\0"
.even
double_max:
.long 0x7fee42d1
.long 0x30273b76
double_min:
.long 0xffee42d1
.long 0x30273b76
NaN:
.long 0x7fffffff
.long 0xffffffff
p_Inf:
.long 0x7ff00000
.long 0x00000000
m_Inf:
.long 0xfff00000
.long 0x00000000
.even
#endif ERROR_CHECK
_ldexp:
#ifdef __MSHORT__
movew a7@(12),d0 | get exponent
extl d0
#else
movel a7@(12),d0 | get exponent
#endif
fgetexpd a7@(4),fp1 | extract exponent of 1st arg
fmovel fp1,d1 | d1 serves as accumulator
addl d0,d1 | sum of exp_s of both args
ftwotoxl d0,fp0 | ftwotox to fp0 (as long int!)
fmuld a7@(4),fp0 | fmul value,fp0
fmoved fp0,a7@- | get double from fp0
moveml a7@+,d0-d1
#endif __M68881__
#ifdef sfp004
| add exponent to floating point number
| C Interface
| double ldexp(double value, unsigned int exp);
| returns value * 2**exp
| (int is 16 bits if -mshort, 32 bits if !-mshort)
| performed entirely on the 68881 to avoid overfow as good as possible
|
| hacked for the 68881 by Michael Ritzert, 5.10.90
|
| addresses of the 68881 data port. This choice is fastest when much data is
| transferred between the two processors.
comm = -6 | fpu command reg
resp = -16 | fpu response reg
zahl = 0 | fpu data reg
| waiting loop ...
|
| wait:
| ww: cmpiw #0x8900,a1@(resp)
| beq ww
| is coded directly by
| .byte 0x0c,0x69,0x89,0x00,0xff,0xf0,0x67,0xf8 (a1)
| or
| .long 0x0c6889000, 0x000067f8 (a0)
.text; .even
.globl _ldexp
#ifdef ERROR_CHECK
_Domain:
.ascii "ldexp: NAN\12\15\0"
_Overflow:
.ascii "ldexp: OVERFLOW\12\15\0"
.even
double_max:
.long 0x7fee42d1
.long 0x30273b76
double_min:
.long 0xffee42d1
.long 0x30273b76
NaN:
.long 0x7fffffff
.long 0xffffffff
p_Inf:
.long 0x7ff00000
.long 0x00000000
m_Inf:
.long 0xfff00000
.long 0x00000000
.even
#endif ERROR_CHECK
_ldexp:
lea 0xfffa50,a0 | fpu address
movew #0x4011,a0@(comm) | ftwotox to fp0 (as long int!)
#ifdef __MSHORT__
movew a7@(12),d0 | get exponent
extl d0
#else
movel a7@(12),d0 | get exponent
#endif
cmpiw #0x8900,a0@(resp) | check if fpu is ready
movel d0,a0@ | push arg
.long 0x0c6889000, 0xfff067f8 | wait
movew #0x5423,a0@(comm) | fmul value,fp0
.long 0x0c6889000, 0xfff067f8 | wait
movel a7@(4),a0@ | load value
movel a7@(8),a0@ |
.long 0x0c6889000, 0xfff067f8 | wait
movew #0x7400,a0@(comm) | get double from fp0
.long 0x0c6889000, 0xfff067f8 | wait
movel a0@,d0
movel a0@,d1
#endif sfp004
#ifdef ERROR_CHECK
lea double_max,a0 |
swap d0 | exponent into lower word
cmpw a0@(16),d0 | == NaN ?
beq error_nan |
cmpw a0@(24),d0 | == + Infinity ?
beq error_plus |
swap d0 | result ok,
rts | restore d0
# ifndef __MSHORT__
error_plus:
swap d0
movel #63,_errno | Overflow: errno = ERANGE
moveml d0-d1,a7@- | print error message
pea _Domain | for printf
bra error_exit |
error_nan:
moveml a0@(24),d0-d1 | result = +inf
movel #62,_errno | NAN => errno = EDOM
moveml d0-d1,a7@- | print error message
pea _Overflow | for printf
# else __MSHORT__
error_plus:
swap d0
movew #63,_errno | Overflow: errno = ERANGE
moveml d0-d1,a7@- | print error message
pea _Domain | for printf
bra error_exit |
error_nan:
moveml a0@(24),d0-d1 | result = +inf
movew #62,_errno | NAN => errno = EDOM
moveml d0-d1,a7@- | print error message
pea _Overflow | for printf
# endif __MSHORT__
error_exit:
pea __iob+52 |
jbsr _fprintf |
addql #8,a7 |
moveml a7@+,d0-d1
rts
#else ERROR_CHECK
rts
#endif ERROR_CHECK
#endif /* !__M68881__ && !sfp004 */