| ... | ... | @@ -192,19 +192,15 @@ fn setFeature(comptime Feature: type, cpu: *Target.Cpu, feature: Feature, enable |
| 192 | 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 | 195 | /// If the fine-grained detection of CPU features via Win registry fails, |
| 200 | 196 | /// we fallback to a generic CPU model but we override the feature set |
| 201 | 197 | /// using `SharedUserData` contents. |
| 202 | 198 | /// This is effectively what LLVM does for all ARM chips on Windows. |
| 203 | 199 | fn genericCpuAndNativeFeatures(arch: Target.Cpu.Arch) Target.Cpu { |
| 204 | | var cpu = Target.Cpu{ |
| 200 | var cpu: Target.Cpu = .{ |
| 205 | 201 | .arch = arch, |
| 206 | 202 | .model = Target.Cpu.Model.generic(arch), |
| 207 | | .features = Target.Cpu.Feature.Set.empty, |
| 203 | .features = .empty, |
| 208 | 204 | }; |
| 209 | 205 | |
| 210 | 206 | switch (arch) { |
| ... | ... | @@ -262,52 +258,39 @@ pub fn detectNativeCpuAndFeatures() ?Target.Cpu { |
| 262 | 258 | const current_arch = builtin.cpu.arch; |
| 263 | 259 | const cpu: ?Target.Cpu = switch (current_arch) { |
| 264 | 260 | .aarch64, .aarch64_be => blk: { |
| 265 | | var cores: [128]Target.Cpu = undefined; |
| 266 | | const core_count = getCpuCount(); |
| 267 | | |
| 268 | | if (core_count > cores.len) break :blk null; |
| 269 | | |
| 270 | | var i: usize = 0; |
| 271 | | while (i < core_count) : (i += 1) { |
| 272 | | // Backing datastore |
| 273 | | var registers: [12]u64 = undefined; |
| 274 | | |
| 275 | | // Registry key to system ID register mapping |
| 276 | | // CP 4000 -> MIDR_EL1 |
| 277 | | // CP 4020 -> ID_AA64PFR0_EL1 |
| 278 | | // CP 4021 -> ID_AA64PFR1_EL1 |
| 279 | | // CP 4028 -> ID_AA64DFR0_EL1 |
| 280 | | // CP 4029 -> ID_AA64DFR1_EL1 |
| 281 | | // CP 402C -> ID_AA64AFR0_EL1 |
| 282 | | // CP 402D -> ID_AA64AFR1_EL1 |
| 283 | | // CP 4030 -> ID_AA64ISAR0_EL1 |
| 284 | | // CP 4031 -> ID_AA64ISAR1_EL1 |
| 285 | | // CP 4038 -> ID_AA64MMFR0_EL1 |
| 286 | | // CP 4039 -> ID_AA64MMFR1_EL1 |
| 287 | | // CP 403A -> ID_AA64MMFR2_EL1 |
| 288 | | getCpuInfoFromRegistry(i, .{ |
| 289 | | .{ .key = "CP 4000", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[0])) }, |
| 290 | | .{ .key = "CP 4020", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[1])) }, |
| 291 | | .{ .key = "CP 4021", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[2])) }, |
| 292 | | .{ .key = "CP 4028", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[3])) }, |
| 293 | | .{ .key = "CP 4029", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[4])) }, |
| 294 | | .{ .key = "CP 402C", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[5])) }, |
| 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]; |
| 261 | var registers: [12]u64 = undefined; |
| 262 | |
| 263 | // CP 4000 -> MIDR_EL1 |
| 264 | // CP 4020 -> ID_AA64PFR0_EL1 |
| 265 | // CP 4021 -> ID_AA64PFR1_EL1 |
| 266 | // CP 4028 -> ID_AA64DFR0_EL1 |
| 267 | // CP 4029 -> ID_AA64DFR1_EL1 |
| 268 | // CP 402C -> ID_AA64AFR0_EL1 |
| 269 | // CP 402D -> ID_AA64AFR1_EL1 |
| 270 | // CP 4030 -> ID_AA64ISAR0_EL1 |
| 271 | // CP 4031 -> ID_AA64ISAR1_EL1 |
| 272 | // CP 4038 -> ID_AA64MMFR0_EL1 |
| 273 | // CP 4039 -> ID_AA64MMFR1_EL1 |
| 274 | // CP 403A -> ID_AA64MMFR2_EL1 |
| 275 | getCpuInfoFromRegistry(0, .{ |
| 276 | .{ .key = "CP 4000", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[0])) }, |
| 277 | .{ .key = "CP 4020", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[1])) }, |
| 278 | .{ .key = "CP 4021", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[2])) }, |
| 279 | .{ .key = "CP 4028", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[3])) }, |
| 280 | .{ .key = "CP 4029", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[4])) }, |
| 281 | .{ .key = "CP 402C", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[5])) }, |
| 282 | .{ .key = "CP 402D", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[6])) }, |
| 283 | .{ .key = "CP 4030", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[7])) }, |
| 284 | .{ .key = "CP 4031", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[8])) }, |
| 285 | .{ .key = "CP 4038", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[9])) }, |
| 286 | .{ .key = "CP 4039", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[10])) }, |
| 287 | .{ .key = "CP 403A", .value_type = REG.ValueType.QWORD, .value_buf = @as(*[8]u8, @ptrCast(&registers[11])) }, |
| 288 | }) catch break :blk null; |
| 289 | |
| 290 | break :blk @import("arm.zig").aarch64.detectNativeCpuAndFeatures(current_arch, registers); |
| 309 | 291 | }, |
| 310 | 292 | else => null, |
| 311 | 293 | }; |
| 294 | |
| 312 | 295 | return cpu orelse genericCpuAndNativeFeatures(current_arch); |
| 313 | 296 | } |