diff --git a/mach/powerpc/libem/fif8.s b/mach/powerpc/libem/fif8.s index 052c38cf2..a26c77830 100644 --- a/mach/powerpc/libem/fif8.s +++ b/mach/powerpc/libem/fif8.s @@ -1,38 +1,71 @@ -# -! $Source$ -! $State$ -! $Revision$ - #include "powerpc.h" - + .sect .text -! Multiplies two floats, and returns the fraction and integer. +! 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 +! Kills: cr0 f1 f2 r3 r4 r5 r6 .define .fif8 .fif8: - lfd f0, 8(sp) - lfd f1, 0(sp) - fmul f0, f0, f1 - fabs f1, f0 ! f0 = result - - ! The following chunk does f1 = floor(f1). See page 158 of the book. - - mtfsfi cr7, 3 ! set rounding mode to -inf. - mtfsb0 23 - fctid f2, f1 - fcfid f2, f2 - mcrfs cr7, cr5 - bc IFFALSE, 31, toobig - fmr f1, f2 -toobig: + 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 - fabs f2, f1 ! f2 = fabs(f1) - fsub f2, f2, f1 - stfd f2, 8(sp) - - fneg f2, f1 - fsel f2, f0, f1, f2 - stfd f2, 0(sp) - + ! 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.) + rlwinm r5, r3, 12, 21, 31 ! r5 = IEEE exponent + addic. r5, r5, -1023 ! r5 = nr of integer bits + bc IFTRUE, LT, no_int + cmpi cr0, 0, r5, 21 + bc IFTRUE, LT, small_int + cmpi cr0, 0, r5, 52 + bc IFTRUE, LT, big_int + + ! f1 is an integer without fraction. Jump to calculate + ! fraction f1 = f2 - f1. It will be zero (or perhaps NaN). + fmr f2, 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. + addi r6, r0, 20 + subf r6, r5, r6 + srw r3, r3, r6 + addi r4, r0, 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. + addi r6, r0, 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 bclr ALWAYS, 0, 0 diff --git a/mach/powerpc/ncg/table b/mach/powerpc/ncg/table index 4a99c9d61..08ddd7d2e 100644 --- a/mach/powerpc/ncg/table +++ b/mach/powerpc/ncg/table @@ -2141,16 +2141,17 @@ PATTERNS with STACK gen bl {LABEL, ".cuf8"} - - pat fef $1==INT64 /* Split double */ + + pat fef $1==INT64 /* Split exponent, fraction */ with GPR3 GPR4 kills FPR0, FPR1, GPR6, GPR7 gen bl {LABEL, ".fef8"} yields R4 R3 R5 - - pat fif $1==INT64 /* Multiply and split double (?) */ - with STACK + + pat fif $1==INT64 /* Multiply then split integer, fraction */ + with FPR1 FPR2 + kills FPR1, FPR2, GPR3, GPR4, GPR5, GPR6 gen bl {LABEL, ".fif8"} - + yields F1 F2