feature. See also
. The project being documented here (as the example) is the Zig library itself.
File
Code
const builtin = @import("builtin");
const std = @import("std");
const Variant = enum(u2) {
la32r = 0b00,
la32 = 0b01,
la64 = 0b10,
reserved = 0b11,
};
inline fn bit(input: u32, offset: u5) bool {
return (input >> offset) & 1 != 0;
}
fn setFeature(cpu: *std.Target.Cpu, feature: std.Target.loongarch.Feature, enabled: bool) void {
const idx = @as(std.Target.Cpu.Feature.Set.Index, @backingInt(feature));
if (enabled) cpu.features.addFeature(idx) else cpu.features.removeFeature(idx);
}
pub fn detectNativeCpuAndFeatures(
arch: std.Target.Cpu.Arch,
os: std.Target.Os,
query: std.Target.Query,
) ?std.Target.Cpu {
_ = os;
_ = query;
const variant: Variant = @fromBackingInt(@intCast(cpucfg(1) & 0b11));
var cpu: std.Target.Cpu = .{
.arch = arch,
.model = switch (cpucfg(0) & 0b1111000000000000) {
else => switch (variant) {
.la32r, .la32 => &std.Target.loongarch.cpu.generic_la32,
.la64 => &std.Target.loongarch.cpu.generic_la64,
.reserved => unreachable,
},
0xc000 => &std.Target.loongarch.cpu.la464,
0xd000 => &std.Target.loongarch.cpu.la664,
},
.features = .empty,
};
cpu.features.addFeatureSet(cpu.model.features);
setFeature(&cpu, .@"32s", variant != .la32r);
const cfg2 = cpucfg(2);
const cfg3 = cpucfg(3);
if (builtin.os.tag == .linux) {
const HWCAP = std.os.linux.HWCAP;
const hwcap_bits: usize = if (builtin.link_libc)
std.c.getauxval(std.elf.AT_HWCAP)
else
std.os.linux.getauxval(std.elf.AT_HWCAP);
setFeature(&cpu, .ual, (hwcap_bits & HWCAP.UAL) != 0);
const has_fpu = (hwcap_bits & HWCAP.FPU) != 0;
setFeature(&cpu, .f, has_fpu and bit(cfg2, 1));
setFeature(&cpu, .d, has_fpu and bit(cfg2, 2));
setFeature(&cpu, .lsx, (hwcap_bits & HWCAP.LSX) != 0);
setFeature(&cpu, .lasx, (hwcap_bits & HWCAP.LASX) != 0);
setFeature(&cpu, .lvz, (hwcap_bits & HWCAP.LVZ) != 0);
setFeature(&cpu, .lbt, (hwcap_bits & HWCAP.LBT_X86) != 0 and (hwcap_bits & HWCAP.LBT_ARM) != 0 and (hwcap_bits & HWCAP.LBT_MIPS) != 0);
} else {
setFeature(&cpu, .ual, false);
setFeature(&cpu, .f, false);
setFeature(&cpu, .d, false);
setFeature(&cpu, .lsx, false);
setFeature(&cpu, .lasx, false);
setFeature(&cpu, .lvz, false);
setFeature(&cpu, .lbt, false);
}
setFeature(&cpu, .frecipe, bit(cfg2, 25));
setFeature(&cpu, .div32, bit(cfg2, 26));
setFeature(&cpu, .lam_bh, bit(cfg2, 27));
setFeature(&cpu, .lamcas, bit(cfg2, 28));
setFeature(&cpu, .scq, bit(cfg2, 30));
setFeature(&cpu, .ld_seq_sa, bit(cfg3, 23));
cpu.features.populateDependencies(cpu.arch.allFeaturesList());
return cpu;
}
extern fn zig_loongarch_cpucfg(word: u32, result: *u32) callconv(.c) void;
fn cpucfg(word: u32) u32 {
var result: u32 = undefined;
if (builtin.zig_backend == .stage2_c) {
zig_loongarch_cpucfg(word, &result);
} else {
asm ("cpucfg %[result], %[word]"
: [result] "=r" (result),
: [word] "r" (word),
);
}
return result;
}