math: fix exp2l asm on x86 (raise underflow correctly)
there were two problems: * omitted underflow on subnormal results: exp2l(-16383.5) was calculated as sqrt(2)*2^-16384, the last bits of sqrt(2) are zero so the down scaling does not underflow eventhough the result is in subnormal range * spurious underflow for subnormal inputs: exp2l(0x1p-16400) was evaluated as f2xm1(x)+1 and f2xm1 raised underflow (because inexact subnormal result) the first issue is fixed by raising underflow manually if x is in (-32768,-16382] and not integer (x-0x1p63+0x1p63 != x) the second issue is fixed by treating x in (-0x1p64,0x1p64) specially for these fixes the special case handling was completely rewritten
This commit is contained in:
parent
8dba548628
commit
07039ed856
2 changed files with 80 additions and 69 deletions
|
|
@ -95,42 +95,32 @@ exp:
|
||||||
.type exp2,@function
|
.type exp2,@function
|
||||||
exp2:
|
exp2:
|
||||||
fldl 4(%esp)
|
fldl 4(%esp)
|
||||||
1: pushl $0x467ff000
|
1: sub $12,%esp
|
||||||
flds (%esp) # 16380
|
|
||||||
xorl %eax,%eax
|
|
||||||
pushl $0x80000000
|
|
||||||
push %eax
|
|
||||||
fld %st(1)
|
|
||||||
fabs
|
|
||||||
fucomp %st(1)
|
|
||||||
fnstsw
|
|
||||||
fstp %st(0)
|
|
||||||
sahf
|
|
||||||
ja 3f # |x| > 16380
|
|
||||||
jp 2f # x is nan (avoid invalid except in fistp)
|
|
||||||
fld %st(0)
|
fld %st(0)
|
||||||
fistpl 8(%esp)
|
|
||||||
fildl 8(%esp)
|
|
||||||
fxch %st(1)
|
|
||||||
fsub %st(1)
|
|
||||||
mov $0x3fff,%eax
|
|
||||||
add %eax,8(%esp)
|
|
||||||
f2xm1
|
|
||||||
fld1
|
|
||||||
faddp # 2^(x-rint(x))
|
|
||||||
fldt (%esp) # 2^rint(x)
|
|
||||||
fmulp
|
|
||||||
fstp %st(1)
|
|
||||||
2: add $12,%esp
|
|
||||||
ret
|
|
||||||
|
|
||||||
3: fld %st(0)
|
|
||||||
fstpt (%esp)
|
fstpt (%esp)
|
||||||
fld1
|
|
||||||
mov 8(%esp),%ax
|
mov 8(%esp),%ax
|
||||||
and $0x7fff,%ax
|
and $0x7fff,%ax
|
||||||
cmp $0x7fff,%ax
|
cmp $0x3fff+13,%ax
|
||||||
je 1f # x = +-inf
|
jb 4f # |x| < 8192
|
||||||
|
cmp $0x3fff+15,%ax
|
||||||
|
jae 3f # |x| >= 32768
|
||||||
|
fsts (%esp)
|
||||||
|
cmpl $0xc67ff800,(%esp)
|
||||||
|
jb 2f # x > -16382
|
||||||
|
movl $0x5f000000,(%esp)
|
||||||
|
flds (%esp) # 0x1p63
|
||||||
|
fld %st(1)
|
||||||
|
fsub %st(1)
|
||||||
|
faddp
|
||||||
|
fucomp %st(1)
|
||||||
|
fnstsw
|
||||||
|
sahf
|
||||||
|
je 2f # x - 0x1p63 + 0x1p63 == x
|
||||||
|
movl $1,(%esp)
|
||||||
|
flds (%esp) # 0x1p-149
|
||||||
|
fdiv %st(1)
|
||||||
|
fstps (%esp) # raise underflow
|
||||||
|
2: fld1
|
||||||
fld %st(1)
|
fld %st(1)
|
||||||
frndint
|
frndint
|
||||||
fxch %st(2)
|
fxch %st(2)
|
||||||
|
|
@ -141,3 +131,19 @@ exp2:
|
||||||
fstp %st(1)
|
fstp %st(1)
|
||||||
add $12,%esp
|
add $12,%esp
|
||||||
ret
|
ret
|
||||||
|
3: xor %eax,%eax
|
||||||
|
4: cmp $0x3fff-64,%ax
|
||||||
|
fld1
|
||||||
|
jb 1b # |x| < 0x1p-64
|
||||||
|
fstpt (%esp)
|
||||||
|
fistl 8(%esp)
|
||||||
|
fildl 8(%esp)
|
||||||
|
fsubrp %st(1)
|
||||||
|
addl $0x3fff,8(%esp)
|
||||||
|
f2xm1
|
||||||
|
fld1
|
||||||
|
faddp # 2^(x-rint(x))
|
||||||
|
fldt (%esp) # 2^rint(x)
|
||||||
|
fmulp
|
||||||
|
add $12,%esp
|
||||||
|
ret
|
||||||
|
|
|
||||||
|
|
@ -26,44 +26,32 @@ expm1l:
|
||||||
.type exp2l,@function
|
.type exp2l,@function
|
||||||
exp2l:
|
exp2l:
|
||||||
fldt 8(%rsp)
|
fldt 8(%rsp)
|
||||||
1: mov $0x467ff000,%eax
|
1: fld %st(0)
|
||||||
mov %eax,-16(%rsp)
|
sub $16,%rsp
|
||||||
mov $0x80000000,%eax
|
fstpt (%rsp)
|
||||||
mov %eax,-20(%rsp)
|
mov 8(%rsp),%ax
|
||||||
xor %eax,%eax
|
|
||||||
mov %eax,-24(%rsp)
|
|
||||||
flds -16(%rsp) # 16380
|
|
||||||
fld %st(1)
|
|
||||||
fabs
|
|
||||||
fucom %st(1)
|
|
||||||
fnstsw
|
|
||||||
fstp %st(0)
|
|
||||||
fstp %st(0)
|
|
||||||
sahf
|
|
||||||
ja 3f # |x| > 16380
|
|
||||||
jp 2f # x is nan (avoid invalid except in fistp)
|
|
||||||
fld %st(0)
|
|
||||||
fistpl -16(%rsp)
|
|
||||||
fildl -16(%rsp)
|
|
||||||
fxch %st(1)
|
|
||||||
fsub %st(1)
|
|
||||||
mov $0x3fff,%eax
|
|
||||||
add %eax,-16(%rsp)
|
|
||||||
f2xm1
|
|
||||||
fld1
|
|
||||||
faddp # 2^(x-rint(x))
|
|
||||||
fldt -24(%rsp) # 2^rint(x)
|
|
||||||
fmulp
|
|
||||||
2: fstp %st(1)
|
|
||||||
ret
|
|
||||||
|
|
||||||
3: fld %st(0)
|
|
||||||
fstpt -24(%rsp)
|
|
||||||
fld1
|
|
||||||
mov -15(%rsp),%ax
|
|
||||||
and $0x7fff,%ax
|
and $0x7fff,%ax
|
||||||
cmp $0x7fff,%ax
|
cmp $0x3fff+13,%ax
|
||||||
je 1f # x = +-inf
|
jb 4f # |x| < 8192
|
||||||
|
cmp $0x3fff+15,%ax
|
||||||
|
jae 3f # |x| >= 32768
|
||||||
|
fsts (%rsp)
|
||||||
|
cmpl $0xc67ff800,(%rsp)
|
||||||
|
jb 2f # x > -16382
|
||||||
|
movl $0x5f000000,(%rsp)
|
||||||
|
flds (%rsp) # 0x1p63
|
||||||
|
fld %st(1)
|
||||||
|
fsub %st(1)
|
||||||
|
faddp
|
||||||
|
fucomp %st(1)
|
||||||
|
fnstsw
|
||||||
|
sahf
|
||||||
|
je 2f # x - 0x1p63 + 0x1p63 == x
|
||||||
|
movl $1,(%rsp)
|
||||||
|
flds (%rsp) # 0x1p-149
|
||||||
|
fdiv %st(1)
|
||||||
|
fstps (%rsp) # raise underflow
|
||||||
|
2: fld1
|
||||||
fld %st(1)
|
fld %st(1)
|
||||||
frndint
|
frndint
|
||||||
fxch %st(2)
|
fxch %st(2)
|
||||||
|
|
@ -72,4 +60,21 @@ exp2l:
|
||||||
faddp # 2^(x-rint(x))
|
faddp # 2^(x-rint(x))
|
||||||
1: fscale
|
1: fscale
|
||||||
fstp %st(1)
|
fstp %st(1)
|
||||||
|
add $16,%rsp
|
||||||
|
ret
|
||||||
|
3: xor %eax,%eax
|
||||||
|
4: cmp $0x3fff-64,%ax
|
||||||
|
fld1
|
||||||
|
jb 1b # |x| < 0x1p-64
|
||||||
|
fstpt (%rsp)
|
||||||
|
fistl 8(%rsp)
|
||||||
|
fildl 8(%rsp)
|
||||||
|
fsubrp %st(1)
|
||||||
|
addl $0x3fff,8(%rsp)
|
||||||
|
f2xm1
|
||||||
|
fld1
|
||||||
|
faddp # 2^(x-rint(x))
|
||||||
|
fldt (%rsp) # 2^rint(x)
|
||||||
|
fmulp
|
||||||
|
add $16,%rsp
|
||||||
ret
|
ret
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue