-
Notifications
You must be signed in to change notification settings - Fork 23
/
log_amd64.s
112 lines (109 loc) · 3.48 KB
/
log_amd64.s
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//go:build !tinygo && !noasm
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSS-style
// license that can be found in the LICENSE file.
#include "textflag.h"
#define HSqrt2 7.07106781186547524401e-01 // sqrt(2)/2
#define Ln2Hi 6.9313812256e-01 // 0x3f317180
#define Ln2Lo 9.0580006145e-06 // 0x3717f7d1
#define L1 6.6666668653e-01 // 0x3f2aaaab
#define L2 4.0000000596e-01 // 0x3ecccccd
#define L3 2.8571429849e-01 // 0x3e924925
#define L4 2.2222198546e-01 // 0x3e638e29
#define L5 1.8183572590e-01 // 0x3e3a3325
#define L6 1.5313838422e-01 // 0x3e1cd04f
#define L7 1.4798198640e-01 // 0x3e178897
#define NaN 0x7FE00000
#define PosInf 0x7F800000
#define NegInf 0xFF800000
// func archLog(x float64) float64
TEXT ·archLog(SB),NOSPLIT,$0
// test bits for special cases
MOVL x+0(FP), BX
MOVQ $~(1<<31), AX // sign bit mask
ANDQ BX, AX
JEQ isZero
MOVL $0, AX
CMPL AX, BX
JGT isNegative
MOVL $PosInf, AX
CMPQ AX, BX
JLE isInfOrNaN
// f1, ki := math.Frexp(x); k := float64(ki)
MOVL BX, X0
MOVL $0x007FFFFF, AX
MOVL AX, X2
ANDPS X0, X2
MOVSS $0.5, X0 // 0x3FE0000000000000
ORPS X0, X2 // X2= f1
SHRQ $23, BX
ANDL $0xFF, BX
SUBL $0x7E, BX
CVTSL2SS BX, X1 // x1= k, x2= f1
// if f1 < math.Sqrt2/2 { k -= 1; f1 *= 2 }
MOVSS $HSqrt2, X0 // x0= 0.7071, x1= k, x2= f1
CMPSS X2, X0, 5 // cmpnlt; x0= 0 or ^0, x1= k, x2 = f1
MOVSS $1.0, X3 // x0= 0 or ^0, x1= k, x2 = f1, x3= 1
ANDPS X0, X3 // x0= 0 or ^0, x1= k, x2 = f1, x3= 0 or 1
SUBSS X3, X1 // x0= 0 or ^0, x1= k, x2 = f1, x3= 0 or 1
MOVSS $1.0, X0 // x0= 1, x1= k, x2= f1, x3= 0 or 1
ADDSS X0, X3 // x0= 1, x1= k, x2= f1, x3= 1 or 2
MULSS X3, X2 // x0= 1, x1= k, x2= f1
// f := f1 - 1
SUBSS X0, X2 // x1= k, x2= f
// s := f / (2 + f)
MOVSS $2.0, X0
ADDSS X2, X0
MOVUPS X2, X3
DIVSS X0, X3 // x1=k, x2= f, x3= s
// s2 := s * s
MOVUPS X3, X4 // x1= k, x2= f, x3= s
MULSS X4, X4 // x1= k, x2= f, x3= s, x4= s2
// s4 := s2 * s2
MOVUPS X4, X5 // x1= k, x2= f, x3= s, x4= s2
MULSS X5, X5 // x1= k, x2= f, x3= s, x4= s2, x5= s4
// t1 := s2 * (L1 + s4*(L3+s4*(L5+s4*L7)))
MOVSS $L7, X6
MULSS X5, X6
ADDSS $L5, X6
MULSS X5, X6
ADDSS $L3, X6
MULSS X5, X6
ADDSS $L1, X6
MULSS X6, X4 // x1= k, x2= f, x3= s, x4= t1, x5= s4
// t2 := s4 * (L2 + s4*(L4+s4*L6))
MOVSS $L6, X6
MULSS X5, X6
ADDSS $L4, X6
MULSS X5, X6
ADDSS $L2, X6
MULSS X6, X5 // x1= k, x2= f, x3= s, x4= t1, x5= t2
// R := t1 + t2
ADDSS X5, X4 // x1= k, x2= f, x3= s, x4= R
// hfsq := 0.5 * f * f
MOVSS $0.5, X0
MULSS X2, X0
MULSS X2, X0 // x0= hfsq, x1= k, x2= f, x3= s, x4= R
// return k*Ln2Hi - ((hfsq - (s*(hfsq+R) + k*Ln2Lo)) - f)
ADDSS X0, X4 // x0= hfsq, x1= k, x2= f, x3= s, x4= hfsq+R
MULSS X4, X3 // x0= hfsq, x1= k, x2= f, x3= s*(hfsq+R)
MOVSS $Ln2Lo, X4
MULSS X1, X4 // x4= k*Ln2Lo
ADDSS X4, X3 // x0= hfsq, x1= k, x2= f, x3= s*(hfsq+R)+k*Ln2Lo
SUBSS X3, X0 // x0= hfsq-(s*(hfsq+R)+k*Ln2Lo), x1= k, x2= f
SUBSS X2, X0 // x0= (hfsq-(s*(hfsq+R)+k*Ln2Lo))-f, x1= k
MULSS $Ln2Hi, X1 // x0= (hfsq-(s*(hfsq+R)+k*Ln2Lo))-f, x1= k*Ln2Hi
SUBSS X0, X1 // x1= k*Ln2Hi-((hfsq-(s*(hfsq+R)+k*Ln2Lo))-f)
MOVSS X1, ret+8(FP)
RET
isInfOrNaN:
MOVL BX, ret+8(FP) // +Inf or NaN, return x
RET
isNegative:
MOVL $NaN, AX
MOVL AX, ret+8(FP) // return NaN
RET
isZero:
MOVL $NegInf, AX
MOVL AX, ret+8(FP) // return -Inf
RET