ack/mach/powerpc/libem/fif8.s

68 lines
1.6 KiB
ArmAsm
Raw Normal View History

2007-11-02 18:56:58 +00:00
.sect .text
! Multiplies two double-precision floats, then splits the product into
! integer and fraction, like modf(3) in C. On entry:
! f1 = float
! f2 = other float
! Yields:
! f1 = fraction
! f2 = integer
2007-11-02 18:56:58 +00:00
.define .fif8
.fif8:
fmul f1, f1, f2
stfdu f1, -8(sp) ! push f1 = product
lwz r3, 0(sp) ! r3 = high word
lwz r4, 4(sp) ! r4 = low word
! IEEE double-precision format:
! sign exponent fraction
! 0 1..11 12..63
! Subtract 1023 from the IEEE exponent. If the result is from
! 0 to 51, then the IEEE fraction has that many integer bits.
! (IEEE has an implicit 1 before its fraction. If the IEEE
! fraction has 0 integer bits, we still have an integer.)
extrwi r5, r3, 11, 1 ! r5 = IEEE exponent
addic. r5, r5, -1023 ! r5 = nr of integer bits
blt no_int
cmpwi r5, 21
blt small_int
cmpwi r5, 52
blt big_int
! f1 is an integer without fraction (or infinity or NaN).
fmr f2, f1 ! integer = f1
b subtract
no_int:
! f1 is a fraction without integer.
fsub f2, f1, f1 ! integer = zero
b done
small_int:
! f1 has r5 = 0 to 20 integer bits in the IEEE fraction.
! High word has 20 - r5 fraction bits.
li r6, 20
subf r6, r5, r6
srw r3, r3, r6
li r4, 0 ! clear low word
slw r3, r3, r6 ! clear fraction in high word
b move_int
big_int:
! f1 has r5 = 21 to 51 to integer bits.
! Low word has 52 - r5 fraction bits.
li r6, 52
subf r6, r5, r6
srw r4, r4, r6
slw r4, r4, r6 ! clear fraction in low word
move_int:
stw r3, 0(sp)
stw r4, 4(sp)
lfd f2, 0(sp) ! f2 = integer
subtract:
fsub f1, f1, f2 ! fraction = value - integer
done:
addi sp, sp, 8 ! restore stack pointer
blr