Commit 7c74edec8d

Felix Queißner <git@mq32.de>
2024-10-04 22:53:28
Adds new cpu architectures propeller1 and propeller2. (#21563)
* Adds new cpu architectures propeller1 and propeller2. These cpu architectures allow targeting the Parallax Propeller 1 and Propeller 2, which are both very special microcontrollers with 512 registers and 8 cpu cores. Resolves #21559 * Adds std.elf.EM.PROPELLER and std.elf.EM.PROPELLER2 * Fixes missing switch prongs in src/codegen/llvm.zig * Fixes order in std.Target.Arch --------- Co-authored-by: Felix "xq" Queißner <git@random-projects.net>
1 parent 3e62cb5
lib/std/Target/propeller.zig
@@ -0,0 +1,20 @@
+const std = @import("../std.zig");
+const CpuFeature = std.Target.Cpu.Feature;
+const CpuModel = std.Target.Cpu.Model;
+
+pub const Feature = enum {};
+
+pub const featureSet = CpuFeature.FeatureSetFns(Feature).featureSet;
+pub const featureSetHas = CpuFeature.FeatureSetFns(Feature).featureSetHas;
+pub const featureSetHasAny = CpuFeature.FeatureSetFns(Feature).featureSetHasAny;
+pub const featureSetHasAll = CpuFeature.FeatureSetFns(Feature).featureSetHasAll;
+
+pub const all_features: [0]CpuFeature = .{};
+
+pub const cpu = struct {
+    pub const generic = CpuModel{
+        .name = "generic",
+        .llvm_name = null,
+        .features = featureSet(&[_]Feature{}),
+    };
+};
lib/std/builtin.zig
@@ -236,6 +236,17 @@ pub const AddressSpace = enum(u5) {
     flash3,
     flash4,
     flash5,
+
+    // Propeller address spaces.
+
+    /// This address space only addresses the cog-local ram.
+    cog,
+
+    /// This address space only addresses shared hub ram.
+    hub,
+
+    /// This address space only addresses the "lookup" ram
+    lut,
 };
 
 /// This data structure is used by the Zig language code generation and
lib/std/elf.zig
@@ -1628,6 +1628,14 @@ pub const EM = enum(u16) {
     /// Adapteva's Epiphany architecture
     ADAPTEVA_EPIPHANY = 0x1223,
 
+    /// Parallax Propeller (P1)
+    /// This value is an unofficial ELF value used in: https://github.com/parallaxinc/propgcc
+    PROPELLER = 0x5072,
+
+    /// Parallax Propeller 2 (P2)
+    /// This value is an unofficial ELF value used in: https://github.com/ne75/llvm-project
+    PROPELLER2 = 300,
+
     _,
 };
 
lib/std/Target.zig
@@ -648,6 +648,7 @@ pub const wasm = @import("Target/wasm.zig");
 pub const x86 = @import("Target/x86.zig");
 pub const xcore = @import("Target/xcore.zig");
 pub const xtensa = @import("Target/xtensa.zig");
+pub const propeller = @import("Target/propeller.zig");
 
 pub const Abi = enum {
     none,
@@ -882,6 +883,9 @@ pub fn toElfMachine(target: Target) std.elf.EM {
         .xcore => .XCORE,
         .xtensa => .XTENSA,
 
+        .propeller1 => .PROPELLER,
+        .propeller2 => .PROPELLER2,
+
         .nvptx,
         .nvptx64,
         .spirv,
@@ -941,6 +945,8 @@ pub fn toCoffMachine(target: Target) std.coff.MachineType {
         .wasm64,
         .xcore,
         .xtensa,
+        .propeller1,
+        .propeller2,
         => .UNKNOWN,
     };
 }
@@ -1156,6 +1162,8 @@ pub const Cpu = struct {
         powerpcle,
         powerpc64,
         powerpc64le,
+        propeller1,
+        propeller2,
         riscv32,
         riscv64,
         s390x,
@@ -1309,6 +1317,14 @@ pub const Cpu = struct {
             };
         }
 
+        /// Returns if the architecture is a Parallax propeller architecture.
+        pub inline fn isPropeller(arch: Arch) bool {
+            return switch (arch) {
+                .propeller1, .propeller2 => true,
+                else => false,
+            };
+        }
+
         pub fn parseCpuModel(arch: Arch, cpu_name: []const u8) !*const Cpu.Model {
             for (arch.allCpuModels()) |cpu| {
                 if (std.mem.eql(u8, cpu_name, cpu.name)) {
@@ -1353,6 +1369,8 @@ pub const Cpu = struct {
                 .loongarch32,
                 .loongarch64,
                 .arc,
+                .propeller1,
+                .propeller2,
                 => .little,
 
                 .armeb,
@@ -1385,6 +1403,10 @@ pub const Cpu = struct {
                 .input, .output, .uniform => is_spirv,
                 // TODO this should also check how many flash banks the cpu has
                 .flash, .flash1, .flash2, .flash3, .flash4, .flash5 => arch == .avr,
+
+                // Propeller address spaces:
+                .cog, .hub => arch.isPropeller(),
+                .lut => (arch == .propeller2),
             };
         }
 
@@ -1405,6 +1427,7 @@ pub const Cpu = struct {
                 .nvptx, .nvptx64 => "nvptx",
                 .wasm32, .wasm64 => "wasm",
                 .spirv, .spirv32, .spirv64 => "spirv",
+                .propeller1, .propeller2 => "propeller",
                 else => @tagName(arch),
             };
         }
@@ -1819,6 +1842,8 @@ pub const DynamicLinker = struct {
                 .spirv,
                 .spirv32,
                 .spirv64,
+                .propeller1,
+                .propeller2,
                 => none,
 
                 // TODO go over each item in this list and either move it to the above list, or
@@ -1928,6 +1953,8 @@ pub fn ptrBitWidth_cpu_abi(cpu: Cpu, abi: Abi) u16 {
         .spirv32,
         .loongarch32,
         .xtensa,
+        .propeller1,
+        .propeller2,
         => 32,
 
         .aarch64,
@@ -2432,6 +2459,8 @@ pub fn cTypeAlignment(target: Target, c_type: CType) u16 {
             .kalimba,
             .spu_2,
             .xtensa,
+            .propeller1,
+            .propeller2,
             => 4,
 
             .amdgcn,
@@ -2536,6 +2565,8 @@ pub fn cTypePreferredAlignment(target: Target, c_type: CType) u16 {
             .kalimba,
             .spu_2,
             .xtensa,
+            .propeller1,
+            .propeller2,
             => 4,
 
             .arc,
src/codegen/llvm.zig
@@ -88,7 +88,10 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 {
 
         .kalimba,
         .spu_2,
+        .propeller1,
+        .propeller2,
         => unreachable, // Gated by hasLlvmSupport().
+
     };
     try llvm_triple.appendSlice(llvm_arch);
 
@@ -281,7 +284,7 @@ pub fn targetArch(arch_tag: std.Target.Cpu.Arch) llvm.ArchType {
         .wasm32 => .wasm32,
         .wasm64 => .wasm64,
         .ve => .ve,
-        .spu_2 => .UnknownArch,
+        .propeller1, .propeller2, .spu_2 => .UnknownArch,
     };
 }
 
@@ -12714,6 +12717,8 @@ pub fn initializeLLVMTarget(arch: std.Target.Cpu.Arch) void {
         // LLVM does does not have a backend for these.
         .kalimba,
         .spu_2,
+        .propeller1,
+        .propeller2,
         => unreachable,
     }
 }
src/codegen/spirv.zig
@@ -1856,6 +1856,9 @@ const NavGen = struct {
             .flash3,
             .flash4,
             .flash5,
+            .cog,
+            .lut,
+            .hub,
             => unreachable,
         };
     }
src/Sema.zig
@@ -37672,6 +37672,9 @@ pub fn analyzeAsAddressSpace(
         .constant => is_gpu and (ctx == .constant),
         // TODO this should also check how many flash banks the cpu has
         .flash, .flash1, .flash2, .flash3, .flash4, .flash5 => arch == .avr,
+
+        .cog, .hub => arch.isPropeller(),
+        .lut => (arch == .propeller2),
     };
 
     if (!supported) {
src/target.zig
@@ -168,6 +168,8 @@ pub fn hasLlvmSupport(target: std.Target, ofmt: std.Target.ObjectFormat) bool {
         // No LLVM backend exists.
         .kalimba,
         .spu_2,
+        .propeller1,
+        .propeller2,
         => false,
     };
 }
src/Type.zig
@@ -1641,6 +1641,7 @@ pub fn maxIntAlignment(target: std.Target, use_llvm: bool) u16 {
         .avr => 1,
         .msp430 => 2,
         .xcore => 4,
+        .propeller1, .propeller2 => 4,
 
         .arm,
         .armeb,
src/Zcu.zig
@@ -3000,6 +3000,8 @@ pub fn atomicPtrAlignment(
         .spirv32,
         .loongarch32,
         .xtensa,
+        .propeller1,
+        .propeller2,
         => 32,
 
         .amdgcn,