// 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() }