diff options
Diffstat (limited to 'sysdeps/x86_64/fpu/e_powl.S')
-rw-r--r-- | sysdeps/x86_64/fpu/e_powl.S | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/sysdeps/x86_64/fpu/e_powl.S b/sysdeps/x86_64/fpu/e_powl.S index 4fe23c06af..1b3718522d 100644 --- a/sysdeps/x86_64/fpu/e_powl.S +++ b/sysdeps/x86_64/fpu/e_powl.S @@ -38,6 +38,9 @@ p64: .byte 0, 0, 0, 0, 0, 0, 0xf0, 0x43 .type p78,@object p78: .byte 0, 0, 0, 0, 0, 0, 0xd0, 0x44 ASM_SIZE_DIRECTIVE(p78) + .type pm79,@object +pm79: .byte 0, 0, 0, 0, 0, 0, 0, 0x3b + ASM_SIZE_DIRECTIVE(pm79) .section .rodata.cst16,"aM",@progbits,16 @@ -110,9 +113,25 @@ ENTRY(__ieee754_powl) fistpll -8(%rsp) // y : x fildll -8(%rsp) // int(y) : y : x fucomip %st(1),%st // y : x - jne 3f + je 9f + + // If y has absolute value at most 0x1p-79, then any finite + // nonzero x will result in 1. Saturate y to those bounds to + // avoid underflow in the calculation of y*log2(x). + fldl MO(pm79) // 0x1p-79 : y : x + fld %st(1) // y : 0x1p-79 : y : x + fabs // |y| : 0x1p-79 : y : x + fcomip %st(1), %st // 0x1p-79 : y : x + fstp %st(0) // y : x + jnc 3f + fstp %st(0) // pop y + fldl MO(pm79) // 0x1p-79 : x + testb $2, %dl + jnz 3f // y > 0 + fchs // -0x1p-79 : x + jmp 3f - /* OK, we have an integer value for y. */ +9: /* OK, we have an integer value for y. */ mov -8(%rsp),%eax mov -4(%rsp),%edx orl $0, %edx |