BSD 4 development
[unix-history] / usr / src / libc / gen / ldexp.s
#
# double ldexp (value, exp)
# double value;
# int exp;
#
# Ldexp returns value*2**exp, if that result is in range.
# If underflow occurs, it returns zero. If overflow occurs,
# it returns a value of appropriate sign and largest
# possible magnitude. In case of either overflow or underflow,
# the external int "errno" is set to ERANGE. Note that errno is
# not modified if no error occurs, so if you intend to test it
# after you use ldexp, you had better set it to something
# other than ERANGE first (zero is a reasonable value to use).
#
# Constants
#
.set erange,34 # error number for range error
.data
.globl _errno # error flag
huge: .word 0x7fff # The largest number that can
.word 0xffff # be represented in a long floating
.word 0xffff # number. This is given in hex in order
.word 0xffff # to avoid floating conversions
#
# Entry point
#
.text
.globl _ldexp
_ldexp: .word 0x0000 # We use r2, but do not save it
movd 4(ap),r0 # Fetch "value"
extzv $7,$8,r0,r2 # r2 := biased exponent
jeql ld1 # If it's zero, we're done
addl2 12(ap),r2 # r2 := new biased exponent
jleq under # if it's <= 0, we have an underflow
cmpl r2,$256 # Otherwise check if it's too big
jgeq over # jump if overflow
#
# Construct the result and return
#
insv r2,$7,$8,r0 # Put the exponent back in the result
ld1: ret
#
# Underflow
#
under: clrd r0 # Result is zero
jbr err # Join general error code
#
# Overflow
#
over: movd huge,r0 # Largest possible floating magnitude
jbc $15,4(ap),err # Jump if argument was positive
mnegd r0,r0 # If arg < 0, make result negative
err: movl $erange,_errno # Indicate range error
ret