]> git.ipfire.org Git - thirdparty/glibc.git/blobdiff - sysdeps/x86_64/fpu/e_powl.S
Prefer https to http for gnu.org and fsf.org URLs
[thirdparty/glibc.git] / sysdeps / x86_64 / fpu / e_powl.S
index 1f68cf01022f4ae899bdc2c7c8155852a49ea340..997736ab539dc3c6d33bc03a6025a6df859efbc9 100644 (file)
@@ -1,5 +1,5 @@
 /* ix87 specific implementation of pow function.
-   Copyright (C) 1996-2016 Free Software Foundation, Inc.
+   Copyright (C) 1996-2019 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
    Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
 
@@ -15,7 +15,7 @@
 
    You should have received a copy of the GNU Lesser General Public
    License along with the GNU C Library; if not, see
-   <http://www.gnu.org/licenses/>.  */
+   <https://www.gnu.org/licenses/>.  */
 
 #include <machine/asm.h>
 #include <x86_64-math-asm.h>
@@ -26,9 +26,9 @@
        .type one,@object
 one:   .double 1.0
        ASM_SIZE_DIRECTIVE(one)
-       .type p3,@object
-p3:    .byte 0, 0, 0, 0, 0, 0, 0x20, 0x40
-       ASM_SIZE_DIRECTIVE(p3)
+       .type p2,@object
+p2:    .byte 0, 0, 0, 0, 0, 0, 0x10, 0x40
+       ASM_SIZE_DIRECTIVE(p2)
        .type p63,@object
 p63:   .byte 0, 0, 0, 0, 0, 0, 0xe0, 0x43
        ASM_SIZE_DIRECTIVE(p63)
@@ -136,12 +136,12 @@ ENTRY(__ieee754_powl)
        jmp     3f
 
 9:     /* OK, we have an integer value for y.  Unless very small
-          (we use < 8), use the algorithm for real exponent to avoid
+          (we use < 4), use the algorithm for real exponent to avoid
           accumulation of errors.  */
-       fldl    MO(p3)          // 8 : y : x
-       fld     %st(1)          // y : 8 : y : x
-       fabs                    // |y| : 8 : y : x
-       fcomip  %st(1), %st     // 8 : y : x
+       fldl    MO(p2)          // 4 : y : x
+       fld     %st(1)          // y : 4 : y : x
+       fabs                    // |y| : 4 : y : x
+       fcomip  %st(1), %st     // 4 : y : x
        fstp    %st(0)          // y : x
        jnc     3f
        mov     -8(%rsp),%eax
@@ -184,9 +184,15 @@ ENTRY(__ieee754_powl)
 30:    fldt    8(%rsp)         // x : y
        fldl    MO(one)         // 1.0 : x : y
        fucomip %st(1),%st      // x : y
-       je      31f
-       fxch                    // y : x
-31:    fstp    %st(1)
+       je      32f
+31:    /* At least one argument NaN, and result should be NaN.  */
+       faddp
+       ret
+32:    jc      31b
+       /* pow (1, NaN); check if the NaN signaling.  */
+       testb   $0x40, 31(%rsp)
+       jz      31b
+       fstp    %st(1)
        ret
 
        .align ALIGNARG(4)
@@ -217,12 +223,24 @@ ENTRY(__ieee754_powl)
        cfi_adjust_cfa_offset (-40)
        ret
 
-       // pow(x,±0) = 1
+       // pow(x,±0) = 1, unless x is sNaN
        .align ALIGNARG(4)
 11:    fstp    %st(0)          // pop y
+       fldt    8(%rsp)         // x
+       fxam
+       fnstsw
+       andb    $0x45, %ah
+       cmpb    $0x01, %ah
+       je      112f            // x is NaN
+111:   fstp    %st(0)
        fldl    MO(one)
        ret
 
+112:   testb   $0x40, 15(%rsp)
+       jnz     111b
+       fadd    %st(0)
+       ret
+
        // y == ±inf
        .align ALIGNARG(4)
 12:    fstp    %st(0)          // pop y
@@ -255,6 +273,7 @@ ENTRY(__ieee754_powl)
 
        .align ALIGNARG(4)
 13:    fldt    8(%rsp)         // load x == NaN
+       fadd    %st(0)
        ret
 
        .align ALIGNARG(4)