| ... | ... | @@ -228,30 +228,40 @@ pub const Target = union(enum) { |
| 228 | 228 | |
| 229 | 229 | var it = mem.tokenize(features_text, ","); |
| 230 | 230 | while (it.next()) |item_text| { |
| 231 | | const feature_name = blk: { |
| 232 | | if (mem.startsWith(u8, item_text, "+")) { |
| 233 | | switch (mode) { |
| 234 | | .unknown, .baseline => mode = .baseline, |
| 235 | | .whitelist => return error.InvalidCpuFeatures, |
| 236 | | } |
| 237 | | break :blk item_text[1..]; |
| 238 | | } else if (mem.startsWith(u8, item_text, "-")) { |
| 239 | | switch (mode) { |
| 240 | | .unknown, .baseline => mode = .baseline, |
| 241 | | .whitelist => return error.InvalidCpuFeatures, |
| 242 | | } |
| 243 | | break :blk item_text[1..]; |
| 244 | | } else { |
| 245 | | switch (mode) { |
| 246 | | .unknown, .whitelist => mode = .whitelist, |
| 247 | | .baseline => return error.InvalidCpuFeatures, |
| 248 | | } |
| 249 | | break :blk item_text; |
| 231 | var feature_name: []const u8 = undefined; |
| 232 | var op: enum { |
| 233 | add, |
| 234 | sub, |
| 235 | } = undefined; |
| 236 | if (mem.startsWith(u8, item_text, "+")) { |
| 237 | switch (mode) { |
| 238 | .unknown, .baseline => mode = .baseline, |
| 239 | .whitelist => return error.InvalidCpuFeatures, |
| 250 | 240 | } |
| 251 | | }; |
| 241 | op = .add; |
| 242 | feature_name = item_text[1..]; |
| 243 | } else if (mem.startsWith(u8, item_text, "-")) { |
| 244 | switch (mode) { |
| 245 | .unknown, .baseline => mode = .baseline, |
| 246 | .whitelist => return error.InvalidCpuFeatures, |
| 247 | } |
| 248 | op = .sub; |
| 249 | feature_name = item_text[1..]; |
| 250 | } else { |
| 251 | switch (mode) { |
| 252 | .unknown, .whitelist => mode = .whitelist, |
| 253 | .baseline => return error.InvalidCpuFeatures, |
| 254 | } |
| 255 | op = .add; |
| 256 | feature_name = item_text; |
| 257 | } |
| 252 | 258 | for (arch.allFeaturesList()) |feature, index| { |
| 253 | 259 | if (mem.eql(u8, feature_name, feature.name)) { |
| 254 | | set |= @splat(2, @as(Cpu.Feature.Set, 1) << @intCast(u7, index)); |
| 260 | const one_bit = @as(Cpu.Feature.Set, 1) << @intCast(u7, index); |
| 261 | switch (op) { |
| 262 | .add => set |= @splat(2, one_bit), |
| 263 | .sub => set &= @splat(2, ~one_bit), |
| 264 | } |
| 255 | 265 | break; |
| 256 | 266 | } |
| 257 | 267 | } else { |
| ... | ... | @@ -1050,3 +1060,13 @@ pub const Target = union(enum) { |
| 1050 | 1060 | return .unavailable; |
| 1051 | 1061 | } |
| 1052 | 1062 | }; |
| 1063 | |
| 1064 | test "parseCpuFeatureSet" { |
| 1065 | const set = try @as(Target.Arch, .x86_64).parseCpuFeatureSet("-sse,-avx,-cx8"); |
| 1066 | std.testing.expect(!Target.x86.featureSetHas(set, .sse)); |
| 1067 | std.testing.expect(!Target.x86.featureSetHas(set, .avx)); |
| 1068 | std.testing.expect(!Target.x86.featureSetHas(set, .cx8)); |
| 1069 | // These are expected because they are part of the baseline |
| 1070 | std.testing.expect(Target.x86.featureSetHas(set, .cmov)); |
| 1071 | std.testing.expect(Target.x86.featureSetHas(set, .fxsr)); |
| 1072 | } |