diff --git a/lib/std/debug/Dwarf.zig b/lib/std/debug/Dwarf.zig index 6efc925c69..3bc5fcf4f0 100644 --- a/lib/std/debug/Dwarf.zig +++ b/lib/std/debug/Dwarf.zig @@ -1434,6 +1434,7 @@ pub fn ipRegNum(arch: std.Target.Cpu.Arch) ?u16 { .hexagon => 76, .loongarch32, .loongarch64 => 32, .mips, .mipsel, .mips64, .mips64el => 37, + .powerpc, .powerpcle, .powerpc64, .powerpc64le => 357, .riscv32, .riscv32be, .riscv64, .riscv64be => 32, .s390x => 65, .x86 => 8, @@ -1449,6 +1450,7 @@ pub fn fpRegNum(arch: std.Target.Cpu.Arch) u16 { .hexagon => 30, .loongarch32, .loongarch64 => 22, .mips, .mipsel, .mips64, .mips64el => 30, + .powerpc, .powerpcle, .powerpc64, .powerpc64le => 1, .riscv32, .riscv32be, .riscv64, .riscv64be => 8, .s390x => 11, .x86 => 5, @@ -1464,6 +1466,7 @@ pub fn spRegNum(arch: std.Target.Cpu.Arch) u16 { .hexagon => 29, .loongarch32, .loongarch64 => 3, .mips, .mipsel, .mips64, .mips64el => 29, + .powerpc, .powerpcle, .powerpc64, .powerpc64le => 1, .riscv32, .riscv32be, .riscv64, .riscv64be => 2, .s390x => 15, .x86 => 4, diff --git a/lib/std/debug/SelfInfo/Elf.zig b/lib/std/debug/SelfInfo/Elf.zig index 145fdfa59f..146f41278d 100644 --- a/lib/std/debug/SelfInfo/Elf.zig +++ b/lib/std/debug/SelfInfo/Elf.zig @@ -103,6 +103,10 @@ pub const can_unwind: bool = s: { .mipsel, .mips64, .mips64el, + .powerpc, + .powerpcle, + .powerpc64, + .powerpc64le, .riscv32, .riscv64, .s390x, diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index 93cf96d242..bfc82f33ec 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -9,6 +9,7 @@ else switch (native_arch) { .hexagon => Hexagon, .loongarch32, .loongarch64 => LoongArch, .mips, .mipsel, .mips64, .mips64el => Mips, + .powerpc, .powerpcle, .powerpc64, .powerpc64le => Powerpc, .riscv32, .riscv32be, .riscv64, .riscv64be => Riscv, .s390x => S390x, .x86 => X86, @@ -216,6 +217,14 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native { }, else => null, }, + .powerpc, .powerpcle, .powerpc64, .powerpc64le => switch (builtin.os.tag) { + .linux => .{ + .r = uc.mcontext.gp_regs[0..32].*, + .pc = uc.mcontext.gp_regs[32], + .lr = uc.mcontext.gp_regs[36], + }, + else => null, + }, .riscv32, .riscv64 => switch (builtin.os.tag) { .linux => .{ .r = [1]usize{0} ++ uc.mcontext.gregs[1..].*, // r0 position is used for pc; replace with zero @@ -808,6 +817,114 @@ pub const Mips = extern struct { } }; +/// This is an `extern struct` so that inline assembly in `current` can use field offsets. +pub const Powerpc = extern struct { + /// The numbered general-purpose registers r0 - r31. + r: [32]Gpr, + pc: Gpr, + lr: Gpr, + + pub const Gpr = if (builtin.target.cpu.arch.isPowerPC64()) u64 else u32; + + pub inline fn current() Powerpc { + var ctx: Powerpc = undefined; + asm volatile (if (Gpr == u64) + \\ std 0, 0(10) + \\ std 1, 8(10) + \\ std 2, 16(10) + \\ std 3, 24(10) + \\ std 4, 32(10) + \\ std 5, 40(10) + \\ std 6, 48(10) + \\ std 7, 56(10) + \\ std 8, 64(10) + \\ std 9, 72(10) + \\ std 10, 80(10) + \\ std 11, 88(10) + \\ std 12, 96(10) + \\ std 13, 104(10) + \\ std 14, 112(10) + \\ std 15, 120(10) + \\ std 16, 128(10) + \\ std 17, 136(10) + \\ std 18, 144(10) + \\ std 19, 152(10) + \\ std 20, 160(10) + \\ std 21, 168(10) + \\ std 22, 176(10) + \\ std 23, 184(10) + \\ std 24, 192(10) + \\ std 25, 200(10) + \\ std 26, 208(10) + \\ std 27, 216(10) + \\ std 28, 224(10) + \\ std 29, 232(10) + \\ std 30, 240(10) + \\ std 31, 248(10) + \\ mflr 8 + \\ std 8, 264(10) + \\ bl 1f + \\1: + \\ mflr 8 + \\ std 8, 256(10) + \\ ld 8, 64(10) + else + \\ stw 0, 0(10) + \\ stw 1, 4(10) + \\ stw 2, 8(10) + \\ stw 3, 12(10) + \\ stw 4, 16(10) + \\ stw 5, 20(10) + \\ stw 6, 24(10) + \\ stw 7, 28(10) + \\ stw 8, 32(10) + \\ stw 9, 36(10) + \\ stw 10, 40(10) + \\ stw 11, 44(10) + \\ stw 12, 48(10) + \\ stw 13, 52(10) + \\ stw 14, 56(10) + \\ stw 15, 60(10) + \\ stw 16, 64(10) + \\ stw 17, 68(10) + \\ stw 18, 72(10) + \\ stw 19, 76(10) + \\ stw 20, 80(10) + \\ stw 21, 84(10) + \\ stw 22, 88(10) + \\ stw 23, 92(10) + \\ stw 24, 96(10) + \\ stw 25, 100(10) + \\ stw 26, 104(10) + \\ stw 27, 108(10) + \\ stw 28, 112(10) + \\ stw 29, 116(10) + \\ stw 30, 120(10) + \\ stw 31, 124(10) + \\ mflr 8 + \\ stw 8, 132(10) + \\ bl 1f + \\1: + \\ mflr 8 + \\ stw 8, 128(10) + \\ lwz 8, 32(10) + : + : [gprs] "{r10}" (&ctx), + : .{ .lr = true, .memory = true }); + return ctx; + } + + pub fn dwarfRegisterBytes(ctx: *Powerpc, register_num: u16) DwarfRegisterError![]u8 { + switch (register_num) { + 0...31 => return @ptrCast(&ctx.r[register_num]), + 65 => return @ptrCast(&ctx.lr), + 357 => return @ptrCast(&ctx.pc), + + else => return error.InvalidRegister, + } + } +}; + /// This is an `extern struct` so that inline assembly in `current` can use field offsets. pub const Riscv = extern struct { /// The numbered general-purpose registers r0 - r31. r0 must be zero.