diff --git a/lib/std/debug/Dwarf.zig b/lib/std/debug/Dwarf.zig index 28d83d463bd9eef5b0edf815ff132b1c24d35c92..439e590daed71cf16c70d1ebea2a6943978f719f 100644 --- a/lib/std/debug/Dwarf.zig +++ b/lib/std/debug/Dwarf.zig @@ -1445,6 +1445,7 @@ pub fn ipRegNum(arch: std.Target.Cpu.Arch) ?u16 { .lanai => 2, .loongarch32, .loongarch64 => 64, .m68k => 26, + .m88k => 64, .mips, .mipsel, .mips64, .mips64el => 66, .or1k => 35, .powerpc, .powerpcle, .powerpc64, .powerpc64le => 67, @@ -1470,6 +1471,7 @@ pub fn fpRegNum(arch: std.Target.Cpu.Arch) u16 { .lanai => 5, .loongarch32, .loongarch64 => 22, .m68k => 14, + .m88k => 30, .mips, .mipsel, .mips64, .mips64el => 30, .or1k => 2, .powerpc, .powerpcle, .powerpc64, .powerpc64le => 1, @@ -1495,6 +1497,7 @@ pub fn spRegNum(arch: std.Target.Cpu.Arch) u16 { .lanai => 4, .loongarch32, .loongarch64 => 3, .m68k => 15, + .m88k => 31, .mips, .mipsel, .mips64, .mips64el => 29, .or1k => 1, .powerpc, .powerpcle, .powerpc64, .powerpc64le => 1, diff --git a/lib/std/debug/SelfInfo/Elf.zig b/lib/std/debug/SelfInfo/Elf.zig index b56e32983f78bf52d89b5a604ba3b6aa169767b3..f8df905fd99c265b8cf9f80c316e1f3663577b2d 100644 --- a/lib/std/debug/SelfInfo/Elf.zig +++ b/lib/std/debug/SelfInfo/Elf.zig @@ -161,6 +161,7 @@ pub const can_unwind: bool = s: { // Not supported yet: arm .openbsd => &.{ .aarch64, + .m88k, .mips64, .mips64el, .riscv64, diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index 29e1731ee4a6b294dd8178237f2fce5954e15ce2..025c5c628a01197e4335a7ad17b77afe62f802c5 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -14,6 +14,7 @@ else switch (native_arch) { .lanai => Lanai, .loongarch32, .loongarch64 => LoongArch, .m68k => M68k, + .m88k => M88k, .mips, .mipsel, .mips64, .mips64el => Mips, .or1k => Or1k, .powerpc, .powerpcle, .powerpc64, .powerpc64le => Powerpc, @@ -62,6 +63,13 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native { }, .pc = @truncate(uc.mcontext.pc), }; + } else if (native_arch == .m88k and native_os == .openbsd) { + // OpenBSD makes no effort to clear the V and E bits of the SXIP register when presenting it + // to user space, so we need to do that here. + return .{ + .r = uc.mcontext.r, + .xip = uc.mcontext.xip & ~@as(u32, 0b11), + }; } else if (native_arch.isMIPS32() and native_os == .linux) { // The O32 kABI uses 64-bit fields for some reason. return .{ @@ -894,6 +902,75 @@ const M68k = extern struct { } }; +/// This is an `extern struct` so that inline assembly in `current` can use field offsets. +const M88k = extern struct { + /// The numbered general-purpose registers r0 - r31. + r: [32]u32, + xip: u32, + + pub inline fn current() M88k { + var ctx: M88k = undefined; + asm volatile ( + \\ st %%r0, %%r2, 0 + \\ st %%r1, %%r2, 4 + \\ st %%r2, %%r2, 8 + \\ st %%r3, %%r2, 12 + \\ st %%r4, %%r2, 16 + \\ st %%r5, %%r2, 20 + \\ st %%r6, %%r2, 24 + \\ st %%r7, %%r2, 28 + \\ st %%r8, %%r2, 32 + \\ st %%r9, %%r2, 36 + \\ st %%r10, %%r2, 40 + \\ st %%r11, %%r2, 44 + \\ st %%r12, %%r2, 48 + \\ st %%r13, %%r2, 52 + \\ st %%r14, %%r2, 56 + \\ st %%r15, %%r2, 60 + \\ st %%r16, %%r2, 64 + \\ st %%r17, %%r2, 68 + \\ st %%r18, %%r2, 72 + \\ st %%r19, %%r2, 76 + \\ st %%r20, %%r2, 80 + \\ st %%r21, %%r2, 84 + \\ st %%r22, %%r2, 88 + \\ st %%r23, %%r2, 92 + \\ st %%r24, %%r2, 96 + \\ st %%r25, %%r2, 100 + \\ st %%r26, %%r2, 104 + \\ st %%r27, %%r2, 108 + \\ st %%r28, %%r2, 112 + \\ st %%r29, %%r2, 116 + \\ st %%r30, %%r2, 120 + \\ st %%r31, %%r2, 124 + \\ bsr.n 1f + \\1: + \\ st %%r1, %%r2, 128 + : + : [ctx] "{r2}" (&ctx), + : .{ .r1 = true, .memory = true }); + return ctx; + } + + pub fn getFp(ctx: *const M88k) u32 { + return ctx.r[30]; + } + pub fn getPc(ctx: *const M88k) u32 { + return ctx.xip; + } + + pub fn dwarfRegisterBytes(ctx: *M88k, register_num: u16) DwarfRegisterError![]u8 { + switch (register_num) { + 0...31 => return @ptrCast(&ctx.r[register_num]), + 64 => return @ptrCast(&ctx.xip), + + 32...63 => return error.UnsupportedRegister, // x0 - x31 + + else => return error.InvalidRegister, + } + } +}; + /// This is an `extern struct` so that inline assembly in `current` can use field offsets. const Mips = extern struct { /// The numbered general-purpose registers r0 - r31. r0 must be zero. @@ -2363,6 +2440,18 @@ const signal_ucontext_t = switch (native_os) { r23_29: [7]u32, r31: u32, }, + // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/m88k/include/signal.h + .m88k => extern struct { + _cookie: i32, + _mask: i32, + mcontext: extern struct { + r: [32]u32, + _epsr: u32, + _fpsr: u32, + _fpcr: u32, + xip: u32, + }, + }, // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/mips64/include/signal.h .mips64, .mips64el => extern struct { _cookie: i64,