zig/lib/std/target/riscv.zig
Andrew Kelley 48c7e6c48b
std.Target.CpuFeatures is now a struct with both CPU and feature set
Previously it was a tagged union which was one of:
 * baseline
 * a specific CPU
 * a set of features

Now, it's possible to have a CPU but also modify the CPU's feature set
on top of that. This is closer to what LLVM does.

This is more correct because Zig's notion of CPUs (and LLVM's) is not
exact CPU models. For example "skylake" is not one very specific model;
there are several different pieces of hardware that match "skylake" that
have different feature sets enabled.
2020-01-22 17:13:31 -05:00

123 lines
3.3 KiB
Zig

const std = @import("../std.zig");
const Cpu = std.Target.Cpu;
pub const Feature = enum {
@"64bit",
a,
c,
d,
e,
f,
m,
relax,
};
pub usingnamespace Cpu.Feature.feature_set_fns(Feature);
pub const all_features = blk: {
const len = @typeInfo(Feature).Enum.fields.len;
std.debug.assert(len <= Cpu.Feature.Set.needed_bit_count);
var result: [len]Cpu.Feature = undefined;
result[@enumToInt(Feature.@"64bit")] = .{
.llvm_name = "64bit",
.description = "Implements RV64",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.a)] = .{
.llvm_name = "a",
.description = "'A' (Atomic Instructions)",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.c)] = .{
.llvm_name = "c",
.description = "'C' (Compressed Instructions)",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.d)] = .{
.llvm_name = "d",
.description = "'D' (Double-Precision Floating-Point)",
.dependencies = featureSet(&[_]Feature{
.f,
}),
};
result[@enumToInt(Feature.e)] = .{
.llvm_name = "e",
.description = "Implements RV32E (provides 16 rather than 32 GPRs)",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.f)] = .{
.llvm_name = "f",
.description = "'F' (Single-Precision Floating-Point)",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.m)] = .{
.llvm_name = "m",
.description = "'M' (Integer Multiplication and Division)",
.dependencies = featureSet(&[_]Feature{}),
};
result[@enumToInt(Feature.relax)] = .{
.llvm_name = "relax",
.description = "Enable Linker relaxation.",
.dependencies = featureSet(&[_]Feature{}),
};
const ti = @typeInfo(Feature);
for (result) |*elem, i| {
elem.index = i;
elem.name = ti.Enum.fields[i].name;
}
break :blk result;
};
pub const cpu = struct {
pub const baseline_rv32 = Cpu{
.name = "baseline_rv32",
.llvm_name = "generic-rv32",
.features = featureSet(&[_]Feature{
.a,
.c,
.d,
.f,
.m,
.relax,
}),
};
pub const baseline_rv64 = Cpu{
.name = "baseline_rv64",
.llvm_name = "generic-rv64",
.features = featureSet(&[_]Feature{
.@"64bit",
.a,
.c,
.d,
.f,
.m,
.relax,
}),
};
pub const generic_rv32 = Cpu{
.name = "generic_rv32",
.llvm_name = "generic-rv32",
.features = featureSet(&[_]Feature{}),
};
pub const generic_rv64 = Cpu{
.name = "generic_rv64",
.llvm_name = "generic-rv64",
.features = featureSet(&[_]Feature{
.@"64bit",
}),
};
};
/// All riscv CPUs, sorted alphabetically by name.
/// TODO: Replace this with usage of `std.meta.declList`. It does work, but stage1
/// compiler has inefficient memory and CPU usage, affecting build times.
pub const all_cpus = &[_]*const Cpu{
&cpu.baseline_rv32,
&cpu.baseline_rv64,
&cpu.generic_rv32,
&cpu.generic_rv64,
};