blob: 51ebf9d4784867f3778331e4dff0228064d81f53 [file] [log] [blame]
// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package runtime
import "internal/cpu"
const (
hwcap_FP = 1 << 0
hwcap_ASIMD = 1 << 1
hwcap_EVTSTRM = 1 << 2
hwcap_AES = 1 << 3
hwcap_PMULL = 1 << 4
hwcap_SHA1 = 1 << 5
hwcap_SHA2 = 1 << 6
hwcap_CRC32 = 1 << 7
hwcap_ATOMICS = 1 << 8
hwcap_FPHP = 1 << 9
hwcap_ASIMDHP = 1 << 10
hwcap_CPUID = 1 << 11
hwcap_ASIMDRDM = 1 << 12
hwcap_JSCVT = 1 << 13
hwcap_FCMA = 1 << 14
hwcap_LRCPC = 1 << 15
hwcap_DCPOP = 1 << 16
hwcap_SHA3 = 1 << 17
hwcap_SM3 = 1 << 18
hwcap_SM4 = 1 << 19
hwcap_ASIMDDP = 1 << 20
hwcap_SHA512 = 1 << 21
hwcap_SVE = 1 << 22
hwcap_ASIMDFHM = 1 << 23
)
func getisar0() uint64
func getisar1() uint64
func getpfr0() uint64
// no hwcap support on FreeBSD aarch64, we need to retrieve the info from
// ID_AA64ISAR0_EL1, ID_AA64ISAR1_EL1 and ID_AA64PFR0_EL1
func archauxv(tag, val uintptr) {
var isar0, isar1, pfr0 uint64
isar0 = getisar0()
isar1 = getisar1()
pfr0 = getpfr0()
// ID_AA64ISAR0_EL1
switch extractBits(isar0, 4, 7) {
case 1:
cpu.HWCap |= hwcap_AES
case 2:
cpu.HWCap |= hwcap_PMULL | hwcap_AES
}
switch extractBits(isar0, 8, 11) {
case 1:
cpu.HWCap |= hwcap_SHA1
}
switch extractBits(isar0, 12, 15) {
case 1:
cpu.HWCap |= hwcap_SHA2
case 2:
cpu.HWCap |= hwcap_SHA2 | hwcap_SHA512
}
switch extractBits(isar0, 16, 19) {
case 1:
cpu.HWCap |= hwcap_CRC32
}
switch extractBits(isar0, 20, 23) {
case 2:
cpu.HWCap |= hwcap_ATOMICS
}
switch extractBits(isar0, 28, 31) {
case 1:
cpu.HWCap |= hwcap_ASIMDRDM
}
switch extractBits(isar0, 32, 35) {
case 1:
cpu.HWCap |= hwcap_SHA3
}
switch extractBits(isar0, 36, 39) {
case 1:
cpu.HWCap |= hwcap_SM3
}
switch extractBits(isar0, 40, 43) {
case 1:
cpu.HWCap |= hwcap_SM4
}
switch extractBits(isar0, 44, 47) {
case 1:
cpu.HWCap |= hwcap_ASIMDDP
}
// ID_AA64ISAR1_EL1
switch extractBits(isar1, 0, 3) {
case 1:
cpu.HWCap |= hwcap_DCPOP
}
switch extractBits(isar1, 12, 15) {
case 1:
cpu.HWCap |= hwcap_JSCVT
}
switch extractBits(isar1, 16, 19) {
case 1:
cpu.HWCap |= hwcap_FCMA
}
switch extractBits(isar1, 20, 23) {
case 1:
cpu.HWCap |= hwcap_LRCPC
}
// ID_AA64PFR0_EL1
switch extractBits(pfr0, 16, 19) {
case 0:
cpu.HWCap |= hwcap_FP
case 1:
cpu.HWCap |= hwcap_FP | hwcap_FPHP
}
switch extractBits(pfr0, 20, 23) {
case 0:
cpu.HWCap |= hwcap_ASIMD
case 1:
cpu.HWCap |= hwcap_ASIMD | hwcap_ASIMDHP
}
switch extractBits(pfr0, 32, 35) {
case 1:
cpu.HWCap |= hwcap_SVE
}
}
func extractBits(data uint64, start, end uint) uint {
return (uint)(data>>start) & ((1 << (end - start + 1)) - 1)
}
//go:nosplit
func cputicks() int64 {
// Currently cputicks() is used in blocking profiler and to seed fastrand().
// nanotime() is a poor approximation of CPU ticks that is enough for the profiler.
return nanotime()
}