| ... | @@ -192,19 +192,15 @@ fn setFeature(comptime Feature: type, cpu: *Target.Cpu, feature: Feature, enable | ... | @@ -192,19 +192,15 @@ fn setFeature(comptime Feature: type, cpu: *Target.Cpu, feature: Feature, enable |
| 192 | if (enabled) cpu.features.addFeature(idx) else cpu.features.removeFeature(idx); | 192 | if (enabled) cpu.features.addFeature(idx) else cpu.features.removeFeature(idx); |
| 193 | } | 193 | } |
| 194 | | 194 | |
| 195 | fn getCpuCount() usize { | | |
| 196 | return std.os.windows.peb().NumberOfProcessors; | | |
| 197 | } | | |
| 198 | | | |
| 199 | /// 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, |
| 200 | /// 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 |
| 201 | /// using `SharedUserData` contents. | 197 | /// using `SharedUserData` contents. |
| 202 | /// 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. |
| 203 | fn genericCpuAndNativeFeatures(arch: Target.Cpu.Arch) Target.Cpu { | 199 | fn genericCpuAndNativeFeatures(arch: Target.Cpu.Arch) Target.Cpu { |
| 204 | var cpu = Target.Cpu{ | 200 | var cpu: Target.Cpu = .{ |
| 205 | .arch = arch, | 201 | .arch = arch, |
| 206 | .model = Target.Cpu.Model.generic(arch), | 202 | .model = Target.Cpu.Model.generic(arch), |
| 207 | .features = Target.Cpu.Feature.Set.empty, | 203 | .features = .empty, |
| 208 | }; | 204 | }; |
| 209 | | 205 | |
| 210 | switch (arch) { | 206 | switch (arch) { |
| ... | @@ -262,52 +258,39 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu { | ... | @@ -262,52 +258,39 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu { |
| 262 | const current_arch = builtin.cpu.arch; | 258 | const current_arch = builtin.cpu.arch; |
| 263 | const cpu: ?Target.Cpu = switch (current_arch) { | 259 | const cpu: ?Target.Cpu = switch (current_arch) { |
| 264 | .aarch64, .aarch64_be => blk: { | 260 | .aarch64, .aarch64_be => blk: { |
| 265 | var cores: [128]Target.Cpu = undefined; | 261 | var registers: [12]u64 = undefined; |
| 266 | const core_count = getCpuCount(); | 262 | |
| 267 | | 263 | // CP 4000 -> MIDR_EL1 |
| 268 | if (core_count > cores.len) break :blk null; | 264 | // CP 4020 -> ID_AA64PFR0_EL1 |
| 269 | | 265 | // CP 4021 -> ID_AA64PFR1_EL1 |
| 270 | var i: usize = 0; | 266 | // CP 4028 -> ID_AA64DFR0_EL1 |
| 271 | while (i < core_count) : (i += 1) { | 267 | // CP 4029 -> ID_AA64DFR1_EL1 |
| 272 | // Backing datastore | 268 | // CP 402C -> ID_AA64AFR0_EL1 |
| 273 | var registers: [12]u64 = undefined; | 269 | // CP 402D -> ID_AA64AFR1_EL1 |
| 274 | | 270 | // CP 4030 -> ID_AA64ISAR0_EL1 |
| 275 | // Registry key to system ID register mapping | 271 | // CP 4031 -> ID_AA64ISAR1_EL1 |
| 276 | // CP 4000 -> MIDR_EL1 | 272 | // CP 4038 -> ID_AA64MMFR0_EL1 |
| 277 | // CP 4020 -> ID_AA64PFR0_EL1 | 273 | // CP 4039 -> ID_AA64MMFR1_EL1 |
| 278 | // CP 4021 -> ID_AA64PFR1_EL1 | 274 | // CP 403A -> ID_AA64MMFR2_EL1 |
| 279 | // CP 4028 -> ID_AA64DFR0_EL1 | 275 | getCpuInfoFromRegistry(0, .{ |
| 280 | // CP 4029 -> ID_AA64DFR1_EL1 | 276 | .{ .key = "CP 4000", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[0])) }, |
| 281 | // CP 402C -> ID_AA64AFR0_EL1 | 277 | .{ .key = "CP 4020", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[1])) }, |
| 282 | // CP 402D -> ID_AA64AFR1_EL1 | 278 | .{ .key = "CP 4021", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[2])) }, |
| 283 | // CP 4030 -> ID_AA64ISAR0_EL1 | 279 | .{ .key = "CP 4028", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[3])) }, |
| 284 | // CP 4031 -> ID_AA64ISAR1_EL1 | 280 | .{ .key = "CP 4029", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[4])) }, |
| 285 | // CP 4038 -> ID_AA64MMFR0_EL1 | 281 | .{ .key = "CP 402C", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[5])) }, |
| 286 | // CP 4039 -> ID_AA64MMFR1_EL1 | 282 | .{ .key = "CP 402D", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[6])) }, |
| 287 | // CP 403A -> ID_AA64MMFR2_EL1 | 283 | .{ .key = "CP 4030", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[7])) }, |
| 288 | getCpuInfoFromRegistry(i, .{ | 284 | .{ .key = "CP 4031", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[8])) }, |
| 289 | .{ .key = "CP 4000", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[0])) }, | 285 | .{ .key = "CP 4038", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[9])) }, |
| 290 | .{ .key = "CP 4020", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[1])) }, | 286 | .{ .key = "CP 4039", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[10])) }, |
| 291 | .{ .key = "CP 4021", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[2])) }, | 287 | .{ .key = "CP 403A", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[11])) }, |
| 292 | .{ .key = "CP 4028", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[3])) }, | 288 | }) catch break :blk null; |
| 293 | .{ .key = "CP 4029", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[4])) }, | 289 | |
| 294 | .{ .key = "CP 402C", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[5])) }, | 290 | break :blk @import("arm.zig").aarch64.detectNativeCpuAndFeatures(current_arch, registers); |
| 295 | .{ .key = "CP 402D", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[6])) }, | | |
| 296 | .{ .key = "CP 4030", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[7])) }, | | |
| 297 | .{ .key = "CP 4031", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[8])) }, | | |
| 298 | .{ .key = "CP 4038", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[9])) }, | | |
| 299 | .{ .key = "CP 4039", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[10])) }, | | |
| 300 | .{ .key = "CP 403A", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[11])) }, | | |
| 301 | }) catch break :blk null; | | |
| 302 | | | |
| 303 | cores[i] = @import("arm.zig").aarch64.detectNativeCpuAndFeatures(current_arch, registers) orelse | | |
| 304 | break :blk null; | | |
| 305 | } | | |
| 306 | | | |
| 307 | // Pick the first core, usually LITTLE in big.LITTLE architecture. | | |
| 308 | break :blk cores[0]; | | |
| 309 | }, | 291 | }, |
| 310 | else => null, | 292 | else => null, |
| 311 | }; | 293 | }; |
| | 294 | |
| 312 | return cpu orelse genericCpuAndNativeFeatures(current_arch); | 295 | return cpu orelse genericCpuAndNativeFeatures(current_arch); |
| 313 | } | 296 | } |