diff --git a/src/math/all_test.go b/src/math/all_test.go index 39b5b33071..a145c5e60b 100644 --- a/src/math/all_test.go +++ b/src/math/all_test.go @@ -1014,6 +1014,8 @@ var vfexpSC = []float64{ 1, // near zero 3.725290298461915e-09, + // denormal + -740, } var expSC = []float64{ 0, @@ -1026,6 +1028,7 @@ var expSC = []float64{ Inf(1), 2.718281828459045, 1.0000000037252903, + 4.2e-322, } var vfexp2SC = []float64{ diff --git a/src/math/exp_amd64.s b/src/math/exp_amd64.s index 2f7fd76fe4..1c2ac8f676 100644 --- a/src/math/exp_amd64.s +++ b/src/math/exp_amd64.s @@ -96,14 +96,13 @@ TEXT ·Exp(SB),NOSPLIT,$0 MULSD X1, X0 ADDSD exprodata<>+8(SB), X0 // return fr * 2**exponent -lastStep: - MOVL $0x3FF, AX // bias - ADDL AX, BX - JLE underflow +ldexp: + ADDL $0x3FF, BX // add bias + JLE denormal CMPL BX, $0x7FF JGE overflow - MOVL $52, CX - SHLQ CX, BX +lastStep: + SHLQ $52, BX MOVQ BX, X1 MULSD X1, X0 MOVSD X0, ret+8(FP) @@ -115,14 +114,22 @@ notFinite: JNE notNegInf // -Inf, return 0 underflow: // return 0 - MOVQ $0, AX - MOVQ AX, ret+8(FP) + MOVQ $0, ret+8(FP) RET overflow: // return +Inf MOVQ $PosInf, BX notNegInf: // NaN or +Inf, return x MOVQ BX, ret+8(FP) RET +denormal: + CMPL BX, $-52 + JL underflow + ADDL $0x3FE, BX // add bias - 1 + SHLQ $52, BX + MOVQ BX, X1 + MULSD X1, X0 + MOVQ $1, BX + JMP lastStep avxfma: MOVSD $LN2U, X2 @@ -149,4 +156,4 @@ avxfma: MULSD X1, X0 VADDSD exprodata<>+16(SB), X0, X1 VFMADD213SD exprodata<>+8(SB), X1, X0 - JMP lastStep + JMP ldexp