cpu: use IsProcessorFeaturePresent to calculate ARM64 on windows

For golang/go#76791

Change-Id: I9500b38b17b5e3e141df8770d82c725c2ba8fd65
Cq-Include-Trybots: luci.golang.try:x_sys-gotip-windows-arm64
Reviewed-on: https://go-review.googlesource.com/c/sys/+/740880
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
diff --git a/cpu/cpu_arm64.go b/cpu/cpu_arm64.go
index af2aa99..6d8eb78 100644
--- a/cpu/cpu_arm64.go
+++ b/cpu/cpu_arm64.go
@@ -47,7 +47,7 @@
 	switch runtime.GOOS {
 	case "freebsd":
 		readARM64Registers()
-	case "linux", "netbsd", "openbsd":
+	case "linux", "netbsd", "openbsd", "windows":
 		doinit()
 	default:
 		// Many platforms don't seem to allow reading these registers.
diff --git a/cpu/cpu_other_arm64.go b/cpu/cpu_other_arm64.go
index 5341e7f..ff74d7a 100644
--- a/cpu/cpu_other_arm64.go
+++ b/cpu/cpu_other_arm64.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build !linux && !netbsd && !openbsd && arm64
+//go:build !linux && !netbsd && !openbsd && !windows && arm64
 
 package cpu
 
diff --git a/cpu/cpu_windows_arm64.go b/cpu/cpu_windows_arm64.go
new file mode 100644
index 0000000..d09e85a
--- /dev/null
+++ b/cpu/cpu_windows_arm64.go
@@ -0,0 +1,42 @@
+// Copyright 2026 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 cpu
+
+import (
+	"golang.org/x/sys/windows"
+)
+
+func doinit() {
+	// set HasASIMD and HasFP to true as per
+	// https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#base-requirements
+	//
+	// The ARM64 version of Windows always presupposes that it's running on an ARMv8 or later architecture.
+	// Both floating-point and NEON support are presumed to be present in hardware.
+	//
+	ARM64.HasASIMD = true
+	ARM64.HasFP = true
+
+	if windows.IsProcessorFeaturePresent(windows.PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) {
+		ARM64.HasAES = true
+		ARM64.HasPMULL = true
+		ARM64.HasSHA1 = true
+		ARM64.HasSHA2 = true
+	}
+	ARM64.HasSHA3 = windows.IsProcessorFeaturePresent(windows.PF_ARM_SHA3_INSTRUCTIONS_AVAILABLE)
+	ARM64.HasCRC32 = windows.IsProcessorFeaturePresent(windows.PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE)
+	ARM64.HasSHA512 = windows.IsProcessorFeaturePresent(windows.PF_ARM_SHA512_INSTRUCTIONS_AVAILABLE)
+	ARM64.HasATOMICS = windows.IsProcessorFeaturePresent(windows.PF_ARM_V81_ATOMIC_INSTRUCTIONS_AVAILABLE)
+	if windows.IsProcessorFeaturePresent(windows.PF_ARM_V82_DP_INSTRUCTIONS_AVAILABLE) {
+		ARM64.HasASIMDDP = true
+		ARM64.HasASIMDRDM = true
+	}
+	if windows.IsProcessorFeaturePresent(windows.PF_ARM_V83_LRCPC_INSTRUCTIONS_AVAILABLE) {
+		ARM64.HasLRCPC = true
+		ARM64.HasSM3 = true
+	}
+	ARM64.HasSVE = windows.IsProcessorFeaturePresent(windows.PF_ARM_SVE_INSTRUCTIONS_AVAILABLE)
+	ARM64.HasSVE2 = windows.IsProcessorFeaturePresent(windows.PF_ARM_SVE2_INSTRUCTIONS_AVAILABLE)
+	ARM64.HasJSCVT = windows.IsProcessorFeaturePresent(windows.PF_ARM_V83_JSCVT_INSTRUCTIONS_AVAILABLE)
+}