log_amd64.s 3.5 KB

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