Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

aarch64

arm.aarch64
pub const aarch64 = struct

File

Code

pub const aarch64 = struct {
    fn setFeature(cpu: *Target.Cpu, feature: Target.aarch64.Feature, enabled: bool) void {
        const idx = @as(Target.Cpu.Feature.Set.Index, @backingInt(feature));

        if (enabled) cpu.features.addFeature(idx) else cpu.features.removeFeature(idx);
    }

    inline fn bitField(input: u64, offset: u6) u4 {
        return @as(u4, @truncate(input >> offset));
    }

    /// Input array should consist of readouts from 12 system registers such that:
    /// 0  -> MIDR_EL1
    /// 1  -> ID_AA64PFR0_EL1
    /// 2  -> ID_AA64PFR1_EL1
    /// 3  -> ID_AA64DFR0_EL1
    /// 4  -> ID_AA64DFR1_EL1
    /// 5  -> ID_AA64AFR0_EL1
    /// 6  -> ID_AA64AFR1_EL1
    /// 7  -> ID_AA64ISAR0_EL1
    /// 8  -> ID_AA64ISAR1_EL1
    /// 9  -> ID_AA64MMFR0_EL1
    /// 10 -> ID_AA64MMFR1_EL1
    /// 11 -> ID_AA64MMFR2_EL1
    pub fn detectNativeCpuAndFeatures(arch: Target.Cpu.Arch, registers: [12]u64) ?Target.Cpu {
        const info = detectNativeCoreInfo(registers[0]);
        const model = cpu_models.isKnown(info, true) orelse return null;

        var cpu = Target.Cpu{
            .arch = arch,
            .model = model,
            .features = Target.Cpu.Feature.Set.empty,
        };

        detectNativeCpuFeatures(&cpu, registers[1..12]);
        addInstructionFusions(&cpu, info);

        return cpu;
    }

    /// Takes readout of MIDR_EL1 register as input.
    fn detectNativeCoreInfo(midr: u64) CoreInfo {
        var info = CoreInfo{
            .implementer = @as(u8, @truncate(midr >> 24)),
            .part = @as(u12, @truncate(midr >> 4)),
        };

        blk: {
            if (info.implementer == 0x41) {
                // ARM Ltd.
                const special_bits: u4 = @truncate(info.part >> 8);
                if (special_bits == 0x0 or special_bits == 0x7) {
                    // TODO Variant and arch encoded differently.
                    break :blk;
                }
            }

            info.variant |= @as(u8, @intCast(@as(u4, @truncate(midr >> 20)))) << 4;
            info.variant |= @as(u4, @truncate(midr));
            info.architecture = @as(u4, @truncate(midr >> 16));
        }

        return info;
    }

    /// Input array should consist of readouts from 11 system registers such that:
    /// 0  -> ID_AA64PFR0_EL1
    /// 1  -> ID_AA64PFR1_EL1
    /// 2  -> ID_AA64DFR0_EL1
    /// 3  -> ID_AA64DFR1_EL1
    /// 4  -> ID_AA64AFR0_EL1
    /// 5  -> ID_AA64AFR1_EL1
    /// 6  -> ID_AA64ISAR0_EL1
    /// 7  -> ID_AA64ISAR1_EL1
    /// 8  -> ID_AA64MMFR0_EL1
    /// 9  -> ID_AA64MMFR1_EL1
    /// 10 -> ID_AA64MMFR2_EL1
    fn detectNativeCpuFeatures(cpu: *Target.Cpu, registers: *const [11]u64) void {
        // ID_AA64PFR0_EL1
        setFeature(cpu, .dit, bitField(registers[0], 48) >= 1);
        setFeature(cpu, .am, bitField(registers[0], 44) >= 1);
        setFeature(cpu, .amvs, bitField(registers[0], 44) >= 2);
        setFeature(cpu, .mpam, bitField(registers[0], 40) >= 1); // MPAM v1.0
        setFeature(cpu, .sel2, bitField(registers[0], 36) >= 1);
        setFeature(cpu, .sve, bitField(registers[0], 32) >= 1);
        setFeature(cpu, .el3, bitField(registers[0], 12) >= 1);
        setFeature(cpu, .ras, bitField(registers[0], 28) >= 1);

        if (bitField(registers[0], 20) < 0xF) blk: {
            if (bitField(registers[0], 16) != bitField(registers[0], 20)) break :blk; // This should never occur

            setFeature(cpu, .neon, true);
            setFeature(cpu, .fp_armv8, true);
            setFeature(cpu, .fullfp16, bitField(registers[0], 20) > 0);
        }

        // ID_AA64PFR1_EL1
        setFeature(cpu, .mpam, bitField(registers[1], 16) > 0 and bitField(registers[0], 40) == 0); // MPAM v0.1
        setFeature(cpu, .mte, bitField(registers[1], 8) >= 1);
        setFeature(cpu, .ssbs, bitField(registers[1], 4) >= 1);
        setFeature(cpu, .bti, bitField(registers[1], 0) >= 1);

        // ID_AA64DFR0_EL1
        setFeature(cpu, .tracev8_4, bitField(registers[2], 40) >= 1);
        setFeature(cpu, .spe, bitField(registers[2], 32) >= 1);
        setFeature(cpu, .perfmon, bitField(registers[2], 8) >= 1 and bitField(registers[2], 8) < 0xF);

        // ID_AA64DFR1_EL1 reserved
        // ID_AA64AFR0_EL1 reserved / implementation defined
        // ID_AA64AFR1_EL1 reserved

        // ID_AA64ISAR0_EL1
        setFeature(cpu, .rand, bitField(registers[6], 60) >= 1);
        setFeature(cpu, .tlb_rmi, bitField(registers[6], 56) >= 1);
        setFeature(cpu, .flagm, bitField(registers[6], 52) >= 1);
        setFeature(cpu, .fp16fml, bitField(registers[6], 48) >= 1);
        setFeature(cpu, .dotprod, bitField(registers[6], 44) >= 1);
        setFeature(cpu, .sm4, bitField(registers[6], 40) >= 1 and bitField(registers[6], 36) >= 1);
        setFeature(cpu, .sha3, bitField(registers[6], 32) >= 1 and bitField(registers[6], 12) >= 2);
        setFeature(cpu, .rdm, bitField(registers[6], 28) >= 1);
        setFeature(cpu, .lse, bitField(registers[6], 20) >= 1);
        setFeature(cpu, .crc, bitField(registers[6], 16) >= 1);
        setFeature(cpu, .sha2, bitField(registers[6], 12) >= 1 and bitField(registers[6], 8) >= 1);
        setFeature(cpu, .aes, bitField(registers[6], 4) >= 1);

        // ID_AA64ISAR1_EL1
        setFeature(cpu, .i8mm, bitField(registers[7], 52) >= 1);
        setFeature(cpu, .bf16, bitField(registers[7], 44) >= 1);
        setFeature(cpu, .predres, bitField(registers[7], 40) >= 1);
        setFeature(cpu, .sb, bitField(registers[7], 36) >= 1);
        setFeature(cpu, .fptoint, bitField(registers[7], 32) >= 1);
        setFeature(cpu, .rcpc, bitField(registers[7], 20) >= 1);
        setFeature(cpu, .rcpc_immo, bitField(registers[7], 20) >= 2);
        setFeature(cpu, .complxnum, bitField(registers[7], 16) >= 1);
        setFeature(cpu, .jsconv, bitField(registers[7], 12) >= 1);
        setFeature(cpu, .pauth, bitField(registers[7], 8) >= 1 or bitField(registers[7], 4) >= 1);
        setFeature(cpu, .ccpp, bitField(registers[7], 0) >= 1);
        setFeature(cpu, .ccdp, bitField(registers[7], 0) >= 2);

        // ID_AA64MMFR0_EL1
        setFeature(cpu, .ecv, bitField(registers[8], 60) >= 1);
        setFeature(cpu, .fgt, bitField(registers[8], 56) >= 1);

        // ID_AA64MMFR1_EL1
        setFeature(cpu, .pan, bitField(registers[9], 20) >= 1);
        setFeature(cpu, .pan_rwv, bitField(registers[9], 20) >= 2);
        setFeature(cpu, .lor, bitField(registers[9], 16) >= 1);
        setFeature(cpu, .vh, bitField(registers[9], 8) >= 1);
        setFeature(cpu, .contextidr_el2, bitField(registers[9], 8) >= 1);

        // ID_AA64MMFR2_EL1
        setFeature(cpu, .nv, bitField(registers[10], 24) >= 1);
        setFeature(cpu, .ccidx, bitField(registers[10], 20) >= 1);
        setFeature(cpu, .uaops, bitField(registers[10], 4) >= 1);
    }

    fn addInstructionFusions(cpu: *Target.Cpu, info: CoreInfo) void {
        switch (info.implementer) {
            0x41 => switch (info.part) {
                0xd4b, 0xd4c => {
                    // According to A78C/X1C Core Software Optimization Guide, CPU fuses certain instructions.
                    setFeature(cpu, .cmp_bcc_fusion, true);
                    setFeature(cpu, .fuse_aes, true);
                },
                else => {},
            },
            else => {},
        }
    }
}