cpu_arm64.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  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. {Name: "dit", Feature: &ARM64.HasDIT},
  38. {Name: "i8mm", Feature: &ARM64.HasI8MM},
  39. }
  40. }
  41. func archInit() {
  42. switch runtime.GOOS {
  43. case "freebsd":
  44. readARM64Registers()
  45. case "linux", "netbsd", "openbsd":
  46. doinit()
  47. default:
  48. // Many platforms don't seem to allow reading these registers.
  49. setMinimalFeatures()
  50. }
  51. }
  52. // setMinimalFeatures fakes the minimal ARM64 features expected by
  53. // TestARM64minimalFeatures.
  54. func setMinimalFeatures() {
  55. ARM64.HasASIMD = true
  56. ARM64.HasFP = true
  57. }
  58. func readARM64Registers() {
  59. Initialized = true
  60. parseARM64SystemRegisters(getisar0(), getisar1(), getpfr0())
  61. }
  62. func parseARM64SystemRegisters(isar0, isar1, pfr0 uint64) {
  63. // ID_AA64ISAR0_EL1
  64. switch extractBits(isar0, 4, 7) {
  65. case 1:
  66. ARM64.HasAES = true
  67. case 2:
  68. ARM64.HasAES = true
  69. ARM64.HasPMULL = true
  70. }
  71. switch extractBits(isar0, 8, 11) {
  72. case 1:
  73. ARM64.HasSHA1 = true
  74. }
  75. switch extractBits(isar0, 12, 15) {
  76. case 1:
  77. ARM64.HasSHA2 = true
  78. case 2:
  79. ARM64.HasSHA2 = true
  80. ARM64.HasSHA512 = true
  81. }
  82. switch extractBits(isar0, 16, 19) {
  83. case 1:
  84. ARM64.HasCRC32 = true
  85. }
  86. switch extractBits(isar0, 20, 23) {
  87. case 2:
  88. ARM64.HasATOMICS = true
  89. }
  90. switch extractBits(isar0, 28, 31) {
  91. case 1:
  92. ARM64.HasASIMDRDM = true
  93. }
  94. switch extractBits(isar0, 32, 35) {
  95. case 1:
  96. ARM64.HasSHA3 = true
  97. }
  98. switch extractBits(isar0, 36, 39) {
  99. case 1:
  100. ARM64.HasSM3 = true
  101. }
  102. switch extractBits(isar0, 40, 43) {
  103. case 1:
  104. ARM64.HasSM4 = true
  105. }
  106. switch extractBits(isar0, 44, 47) {
  107. case 1:
  108. ARM64.HasASIMDDP = true
  109. }
  110. // ID_AA64ISAR1_EL1
  111. switch extractBits(isar1, 0, 3) {
  112. case 1:
  113. ARM64.HasDCPOP = true
  114. }
  115. switch extractBits(isar1, 12, 15) {
  116. case 1:
  117. ARM64.HasJSCVT = true
  118. }
  119. switch extractBits(isar1, 16, 19) {
  120. case 1:
  121. ARM64.HasFCMA = true
  122. }
  123. switch extractBits(isar1, 20, 23) {
  124. case 1:
  125. ARM64.HasLRCPC = true
  126. }
  127. switch extractBits(isar1, 52, 55) {
  128. case 1:
  129. ARM64.HasI8MM = true
  130. }
  131. // ID_AA64PFR0_EL1
  132. switch extractBits(pfr0, 16, 19) {
  133. case 0:
  134. ARM64.HasFP = true
  135. case 1:
  136. ARM64.HasFP = true
  137. ARM64.HasFPHP = true
  138. }
  139. switch extractBits(pfr0, 20, 23) {
  140. case 0:
  141. ARM64.HasASIMD = true
  142. case 1:
  143. ARM64.HasASIMD = true
  144. ARM64.HasASIMDHP = true
  145. }
  146. switch extractBits(pfr0, 32, 35) {
  147. case 1:
  148. ARM64.HasSVE = true
  149. parseARM64SVERegister(getzfr0())
  150. }
  151. switch extractBits(pfr0, 48, 51) {
  152. case 1:
  153. ARM64.HasDIT = true
  154. }
  155. }
  156. func parseARM64SVERegister(zfr0 uint64) {
  157. switch extractBits(zfr0, 0, 3) {
  158. case 1:
  159. ARM64.HasSVE2 = true
  160. }
  161. }
  162. func extractBits(data uint64, start, end uint) uint {
  163. return (uint)(data>>start) & ((1 << (end - start + 1)) - 1)
  164. }