Commit 12b1d57df1

Alex Rønne Petersen <alex@alexrp.com>
2025-10-14 09:32:12
std.debug.cpu_context: add Sparc context
1 parent 3d3aff0
Changed files (1)
lib
std
lib/std/debug/cpu_context.zig
@@ -10,6 +10,7 @@ else switch (native_arch) {
     .loongarch32, .loongarch64 => LoongArch,
     .mips, .mipsel, .mips64, .mips64el => Mips,
     .powerpc, .powerpcle, .powerpc64, .powerpc64le => Powerpc,
+    .sparc, .sparc64 => Sparc,
     .riscv32, .riscv32be, .riscv64, .riscv64be => Riscv,
     .s390x => S390x,
     .x86 => X86,
@@ -858,6 +859,93 @@ const Powerpc = extern struct {
     }
 };
 
+/// This is an `extern struct` so that inline assembly in `current` can use field offsets.
+const Sparc = extern struct {
+    g: [8]Gpr,
+    o: [8]Gpr,
+    l: [8]Gpr,
+    i: [8]Gpr,
+    pc: Gpr,
+
+    pub const Gpr = if (native_arch == .sparc64) u64 else u32;
+
+    pub inline fn current() Sparc {
+        var ctx: Sparc = undefined;
+        asm volatile (if (Gpr == u64)
+                \\ stx %g0, [%l0 + 0]
+                \\ stx %g1, [%l0 + 8]
+                \\ stx %g2, [%l0 + 16]
+                \\ stx %g3, [%l0 + 24]
+                \\ stx %g4, [%l0 + 32]
+                \\ stx %g5, [%l0 + 40]
+                \\ stx %g6, [%l0 + 48]
+                \\ stx %g7, [%l0 + 56]
+                \\ stx %o0, [%l0 + 64]
+                \\ stx %o1, [%l0 + 72]
+                \\ stx %o2, [%l0 + 80]
+                \\ stx %o3, [%l0 + 88]
+                \\ stx %o4, [%l0 + 96]
+                \\ stx %o5, [%l0 + 104]
+                \\ stx %o6, [%l0 + 112]
+                \\ stx %o7, [%l0 + 120]
+                \\ stx %l0, [%l0 + 128]
+                \\ stx %l1, [%l0 + 136]
+                \\ stx %l2, [%l0 + 144]
+                \\ stx %l3, [%l0 + 152]
+                \\ stx %l4, [%l0 + 160]
+                \\ stx %l5, [%l0 + 168]
+                \\ stx %l6, [%l0 + 176]
+                \\ stx %l7, [%l0 + 184]
+                \\ stx %i0, [%l0 + 192]
+                \\ stx %i1, [%l0 + 200]
+                \\ stx %i2, [%l0 + 208]
+                \\ stx %i3, [%l0 + 216]
+                \\ stx %i4, [%l0 + 224]
+                \\ stx %i5, [%l0 + 232]
+                \\ stx %i6, [%l0 + 240]
+                \\ stx %i7, [%l0 + 248]
+                \\ call 1f
+                \\  stx %o7, [%l0 + 256]
+                \\1:
+            else
+                \\ std %g0, [%l0 + 0]
+                \\ std %g2, [%l0 + 8]
+                \\ std %g4, [%l0 + 16]
+                \\ std %g6, [%l0 + 24]
+                \\ std %o0, [%l0 + 32]
+                \\ std %o2, [%l0 + 40]
+                \\ std %o4, [%l0 + 48]
+                \\ std %o6, [%l0 + 56]
+                \\ std %l0, [%l0 + 64]
+                \\ std %l2, [%l0 + 72]
+                \\ std %l4, [%l0 + 80]
+                \\ std %l6, [%l0 + 88]
+                \\ std %i0, [%l0 + 96]
+                \\ std %i2, [%l0 + 104]
+                \\ std %i4, [%l0 + 112]
+                \\ std %i6, [%l0 + 120]
+                \\ call 1f
+                \\  st %o7, [%l0 + 128]
+                \\1:
+            :
+            : [gprs] "{l0}" (&ctx),
+            : .{ .o7 = true, .memory = true });
+        return ctx;
+    }
+
+    pub fn dwarfRegisterBytes(ctx: *Sparc, register_num: u16) DwarfRegisterError![]u8 {
+        switch (register_num) {
+            0...7 => return @ptrCast(&ctx.g[register_num]),
+            8...15 => return @ptrCast(&ctx.o[register_num - 8]),
+            16...23 => return @ptrCast(&ctx.l[register_num - 16]),
+            24...31 => return @ptrCast(&ctx.i[register_num - 24]),
+            32 => return @ptrCast(&ctx.pc),
+
+            else => return error.InvalidRegister,
+        }
+    }
+};
+
 /// This is an `extern struct` so that inline assembly in `current` can use field offsets.
 const Riscv = extern struct {
     /// The numbered general-purpose registers r0 - r31. r0 must be zero.