cpu_arm64.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. // Copyright 2019 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package cpu
  5. import "runtime"
  6. // cacheLineSize is used to prevent false sharing of cache lines.
  7. // We choose 128 because Apple Silicon, a.k.a. M1, has 128-byte cache line size.
  8. // It doesn't cost much and is much more future-proof.
  9. const cacheLineSize = 128
  10. func initOptions() {
  11. options = []option{
  12. {Name: "fp", Feature: &ARM64.HasFP},
  13. {Name: "asimd", Feature: &ARM64.HasASIMD},
  14. {Name: "evstrm", Feature: &ARM64.HasEVTSTRM},
  15. {Name: "aes", Feature: &ARM64.HasAES},
  16. {Name: "fphp", Feature: &ARM64.HasFPHP},
  17. {Name: "jscvt", Feature: &ARM64.HasJSCVT},
  18. {Name: "lrcpc", Feature: &ARM64.HasLRCPC},
  19. {Name: "pmull", Feature: &ARM64.HasPMULL},
  20. {Name: "sha1", Feature: &ARM64.HasSHA1},
  21. {Name: "sha2", Feature: &ARM64.HasSHA2},
  22. {Name: "sha3", Feature: &ARM64.HasSHA3},
  23. {Name: "sha512", Feature: &ARM64.HasSHA512},
  24. {Name: "sm3", Feature: &ARM64.HasSM3},
  25. {Name: "sm4", Feature: &ARM64.HasSM4},
  26. {Name: "sve", Feature: &ARM64.HasSVE},
  27. {Name: "sve2", Feature: &ARM64.HasSVE2},
  28. {Name: "crc32", Feature: &ARM64.HasCRC32},
  29. {Name: "atomics", Feature: &ARM64.HasATOMICS},
  30. {Name: "asimdhp", Feature: &ARM64.HasASIMDHP},
  31. {Name: "cpuid", Feature: &ARM64.HasCPUID},
  32. {Name: "asimrdm", Feature: &ARM64.HasASIMDRDM},
  33. {Name: "fcma", Feature: &ARM64.HasFCMA},
  34. {Name: "dcpop", Feature: &ARM64.HasDCPOP},
  35. {Name: "asimddp", Feature: &ARM64.HasASIMDDP},
  36. {Name: "asimdfhm", Feature: &ARM64.HasASIMDFHM},
  37. }
  38. }
  39. func archInit() {
  40. switch runtime.GOOS {
  41. case "freebsd":
  42. readARM64Registers()
  43. case "linux", "netbsd", "openbsd":
  44. doinit()
  45. default:
  46. // Many platforms don't seem to allow reading these registers.
  47. setMinimalFeatures()
  48. }
  49. }
  50. // setMinimalFeatures fakes the minimal ARM64 features expected by
  51. // TestARM64minimalFeatures.
  52. func setMinimalFeatures() {
  53. ARM64.HasASIMD = true
  54. ARM64.HasFP = true
  55. }
  56. func readARM64Registers() {
  57. Initialized = true
  58. parseARM64SystemRegisters(getisar0(), getisar1(), getpfr0())
  59. }
  60. func parseARM64SystemRegisters(isar0, isar1, pfr0 uint64) {
  61. // ID_AA64ISAR0_EL1
  62. switch extractBits(isar0, 4, 7) {
  63. case 1:
  64. ARM64.HasAES = true
  65. case 2:
  66. ARM64.HasAES = true
  67. ARM64.HasPMULL = true
  68. }
  69. switch extractBits(isar0, 8, 11) {
  70. case 1:
  71. ARM64.HasSHA1 = true
  72. }
  73. switch extractBits(isar0, 12, 15) {
  74. case 1:
  75. ARM64.HasSHA2 = true
  76. case 2:
  77. ARM64.HasSHA2 = true
  78. ARM64.HasSHA512 = true
  79. }
  80. switch extractBits(isar0, 16, 19) {
  81. case 1:
  82. ARM64.HasCRC32 = true
  83. }
  84. switch extractBits(isar0, 20, 23) {
  85. case 2:
  86. ARM64.HasATOMICS = true
  87. }
  88. switch extractBits(isar0, 28, 31) {
  89. case 1:
  90. ARM64.HasASIMDRDM = true
  91. }
  92. switch extractBits(isar0, 32, 35) {
  93. case 1:
  94. ARM64.HasSHA3 = true
  95. }
  96. switch extractBits(isar0, 36, 39) {
  97. case 1:
  98. ARM64.HasSM3 = true
  99. }
  100. switch extractBits(isar0, 40, 43) {
  101. case 1:
  102. ARM64.HasSM4 = true
  103. }
  104. switch extractBits(isar0, 44, 47) {
  105. case 1:
  106. ARM64.HasASIMDDP = true
  107. }
  108. // ID_AA64ISAR1_EL1
  109. switch extractBits(isar1, 0, 3) {
  110. case 1:
  111. ARM64.HasDCPOP = true
  112. }
  113. switch extractBits(isar1, 12, 15) {
  114. case 1:
  115. ARM64.HasJSCVT = true
  116. }
  117. switch extractBits(isar1, 16, 19) {
  118. case 1:
  119. ARM64.HasFCMA = true
  120. }
  121. switch extractBits(isar1, 20, 23) {
  122. case 1:
  123. ARM64.HasLRCPC = true
  124. }
  125. // ID_AA64PFR0_EL1
  126. switch extractBits(pfr0, 16, 19) {
  127. case 0:
  128. ARM64.HasFP = true
  129. case 1:
  130. ARM64.HasFP = true
  131. ARM64.HasFPHP = true
  132. }
  133. switch extractBits(pfr0, 20, 23) {
  134. case 0:
  135. ARM64.HasASIMD = true
  136. case 1:
  137. ARM64.HasASIMD = true
  138. ARM64.HasASIMDHP = true
  139. }
  140. switch extractBits(pfr0, 32, 35) {
  141. case 1:
  142. ARM64.HasSVE = true
  143. parseARM64SVERegister(getzfr0())
  144. }
  145. }
  146. func parseARM64SVERegister(zfr0 uint64) {
  147. switch extractBits(zfr0, 0, 3) {
  148. case 1:
  149. ARM64.HasSVE2 = true
  150. }
  151. }
  152. func extractBits(data uint64, start, end uint) uint {
  153. return (uint)(data>>start) & ((1 << (end - start + 1)) - 1)
  154. }