| ... | @@ -3,11 +3,10 @@ const builtin = @import("builtin"); | ... | @@ -3,11 +3,10 @@ const builtin = @import("builtin"); |
| 3 | const assert = std.debug.assert; | 3 | const assert = std.debug.assert; |
| 4 | const mem = std.mem; | 4 | const mem = std.mem; |
| 5 | const Target = std.Target; | 5 | const Target = std.Target; |
| 6 | | 6 | const WindowsVersion = std.Target.Os.WindowsVersion; |
| 7 | pub const WindowsVersion = std.Target.Os.WindowsVersion; | 7 | const PF = std.os.windows.PF; |
| 8 | pub const PF = std.os.windows.PF; | 8 | const REG = std.os.windows.REG; |
| 9 | pub const REG = std.os.windows.REG; | 9 | const IsProcessorFeaturePresent = std.os.windows.IsProcessorFeaturePresent; |
| 10 | pub const IsProcessorFeaturePresent = std.os.windows.IsProcessorFeaturePresent; | | |
| 11 | | 10 | |
| 12 | /// Returns the highest known WindowsVersion deduced from reported runtime information. | 11 | /// Returns the highest known WindowsVersion deduced from reported runtime information. |
| 13 | /// Discards information about in-between versions we don't differentiate. | 12 | /// Discards information about in-between versions we don't differentiate. |
| ... | @@ -193,21 +192,19 @@ fn setFeature(comptime Feature: type, cpu: *Target.Cpu, feature: Feature, enable | ... | @@ -193,21 +192,19 @@ fn setFeature(comptime Feature: type, cpu: *Target.Cpu, feature: Feature, enable |
| 193 | if (enabled) cpu.features.addFeature(idx) else cpu.features.removeFeature(idx); | 192 | if (enabled) cpu.features.addFeature(idx) else cpu.features.removeFeature(idx); |
| 194 | } | 193 | } |
| 195 | | 194 | |
| 196 | fn getCpuCount() usize { | | |
| 197 | return std.os.windows.peb().NumberOfProcessors; | | |
| 198 | } | | |
| 199 | | | |
| 200 | /// If the fine-grained detection of CPU features via Win registry fails, | 195 | /// If the fine-grained detection of CPU features via Win registry fails, |
| 201 | /// we fallback to a generic CPU model but we override the feature set | 196 | /// we fallback to a generic CPU model but we override the feature set |
| 202 | /// using `SharedUserData` contents. | 197 | /// using `SharedUserData` contents. |
| 203 | /// This is effectively what LLVM does for all ARM chips on Windows. | 198 | /// This is effectively what LLVM does for all ARM chips on Windows. |
| 204 | fn genericCpuAndNativeFeatures(arch: Target.Cpu.Arch) Target.Cpu { | 199 | fn genericCpuAndNativeFeatures(arch: Target.Cpu.Arch) Target.Cpu { |
| 205 | var cpu = Target.Cpu{ | 200 | var cpu: Target.Cpu = .{ |
| 206 | .arch = arch, | 201 | .arch = arch, |
| 207 | .model = Target.Cpu.Model.generic(arch), | 202 | .model = Target.Cpu.Model.generic(arch), |
| 208 | .features = Target.Cpu.Feature.Set.empty, | 203 | .features = .empty, |
| 209 | }; | 204 | }; |
| 210 | | 205 | |
| | 206 | cpu.features.addFeatureSet(cpu.model.features); |
| | 207 | |
| 211 | switch (arch) { | 208 | switch (arch) { |
| 212 | .aarch64, .aarch64_be => { | 209 | .aarch64, .aarch64_be => { |
| 213 | const Feature = Target.aarch64.Feature; | 210 | const Feature = Target.aarch64.Feature; |
| ... | @@ -256,6 +253,8 @@ fn genericCpuAndNativeFeatures(arch: Target.Cpu.Arch) Target.Cpu { | ... | @@ -256,6 +253,8 @@ fn genericCpuAndNativeFeatures(arch: Target.Cpu.Arch) Target.Cpu { |
| 256 | else => {}, | 253 | else => {}, |
| 257 | } | 254 | } |
| 258 | | 255 | |
| | 256 | cpu.features.populateDependencies(cpu.arch.allFeaturesList()); |
| | 257 | |
| 259 | return cpu; | 258 | return cpu; |
| 260 | } | 259 | } |
| 261 | | 260 | |
| ... | @@ -263,52 +262,39 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu { | ... | @@ -263,52 +262,39 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu { |
| 263 | const current_arch = builtin.cpu.arch; | 262 | const current_arch = builtin.cpu.arch; |
| 264 | const cpu: ?Target.Cpu = switch (current_arch) { | 263 | const cpu: ?Target.Cpu = switch (current_arch) { |
| 265 | .aarch64, .aarch64_be => blk: { | 264 | .aarch64, .aarch64_be => blk: { |
| 266 | var cores: [128]Target.Cpu = undefined; | 265 | var registers: [12]u64 = undefined; |
| 267 | const core_count = getCpuCount(); | 266 | |
| 268 | | 267 | // CP 4000 -> MIDR_EL1 |
| 269 | if (core_count > cores.len) break :blk null; | 268 | // CP 4020 -> ID_AA64PFR0_EL1 |
| 270 | | 269 | // CP 4021 -> ID_AA64PFR1_EL1 |
| 271 | var i: usize = 0; | 270 | // CP 4028 -> ID_AA64DFR0_EL1 |
| 272 | while (i < core_count) : (i += 1) { | 271 | // CP 4029 -> ID_AA64DFR1_EL1 |
| 273 | // Backing datastore | 272 | // CP 402C -> ID_AA64AFR0_EL1 |
| 274 | var registers: [12]u64 = undefined; | 273 | // CP 402D -> ID_AA64AFR1_EL1 |
| 275 | | 274 | // CP 4030 -> ID_AA64ISAR0_EL1 |
| 276 | // Registry key to system ID register mapping | 275 | // CP 4031 -> ID_AA64ISAR1_EL1 |
| 277 | // CP 4000 -> MIDR_EL1 | 276 | // CP 4038 -> ID_AA64MMFR0_EL1 |
| 278 | // CP 4020 -> ID_AA64PFR0_EL1 | 277 | // CP 4039 -> ID_AA64MMFR1_EL1 |
| 279 | // CP 4021 -> ID_AA64PFR1_EL1 | 278 | // CP 403A -> ID_AA64MMFR2_EL1 |
| 280 | // CP 4028 -> ID_AA64DFR0_EL1 | 279 | getCpuInfoFromRegistry(0, .{ |
| 281 | // CP 4029 -> ID_AA64DFR1_EL1 | 280 | .{ .key = "CP 4000", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[0])) }, |
| 282 | // CP 402C -> ID_AA64AFR0_EL1 | 281 | .{ .key = "CP 4020", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[1])) }, |
| 283 | // CP 402D -> ID_AA64AFR1_EL1 | 282 | .{ .key = "CP 4021", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[2])) }, |
| 284 | // CP 4030 -> ID_AA64ISAR0_EL1 | 283 | .{ .key = "CP 4028", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[3])) }, |
| 285 | // CP 4031 -> ID_AA64ISAR1_EL1 | 284 | .{ .key = "CP 4029", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[4])) }, |
| 286 | // CP 4038 -> ID_AA64MMFR0_EL1 | 285 | .{ .key = "CP 402C", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[5])) }, |
| 287 | // CP 4039 -> ID_AA64MMFR1_EL1 | 286 | .{ .key = "CP 402D", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[6])) }, |
| 288 | // CP 403A -> ID_AA64MMFR2_EL1 | 287 | .{ .key = "CP 4030", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[7])) }, |
| 289 | getCpuInfoFromRegistry(i, .{ | 288 | .{ .key = "CP 4031", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[8])) }, |
| 290 | .{ .key = "CP 4000", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[0])) }, | 289 | .{ .key = "CP 4038", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[9])) }, |
| 291 | .{ .key = "CP 4020", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[1])) }, | 290 | .{ .key = "CP 4039", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[10])) }, |
| 292 | .{ .key = "CP 4021", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[2])) }, | 291 | .{ .key = "CP 403A", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[11])) }, |
| 293 | .{ .key = "CP 4028", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[3])) }, | 292 | }) catch break :blk null; |
| 294 | .{ .key = "CP 4029", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[4])) }, | 293 | |
| 295 | .{ .key = "CP 402C", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[5])) }, | 294 | break :blk @import("arm.zig").aarch64.detectNativeCpuAndFeatures(current_arch, registers); |
| 296 | .{ .key = "CP 402D", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[6])) }, | | |
| 297 | .{ .key = "CP 4030", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[7])) }, | | |
| 298 | .{ .key = "CP 4031", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[8])) }, | | |
| 299 | .{ .key = "CP 4038", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[9])) }, | | |
| 300 | .{ .key = "CP 4039", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[10])) }, | | |
| 301 | .{ .key = "CP 403A", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[11])) }, | | |
| 302 | }) catch break :blk null; | | |
| 303 | | | |
| 304 | cores[i] = @import("arm.zig").aarch64.detectNativeCpuAndFeatures(current_arch, registers) orelse | | |
| 305 | break :blk null; | | |
| 306 | } | | |
| 307 | | | |
| 308 | // Pick the first core, usually LITTLE in big.LITTLE architecture. | | |
| 309 | break :blk cores[0]; | | |
| 310 | }, | 295 | }, |
| 311 | else => null, | 296 | else => null, |
| 312 | }; | 297 | }; |
| | 298 | |
| 313 | return cpu orelse genericCpuAndNativeFeatures(current_arch); | 299 | return cpu orelse genericCpuAndNativeFeatures(current_arch); |
| 314 | } | 300 | } |