From ef4f6e6c0578288144760437231620efbdb1edd6 Mon Sep 17 00:00:00 2001 From: GasInfinity Date: Wed, 29 Oct 2025 14:35:33 +0100 Subject: [PATCH] feat: add `x86_16` debug `cpu_context` --- lib/std/debug/cpu_context.zig | 41 +++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/lib/std/debug/cpu_context.zig b/lib/std/debug/cpu_context.zig index 9d460a1797..9a0e00d20b 100644 --- a/lib/std/debug/cpu_context.zig +++ b/lib/std/debug/cpu_context.zig @@ -19,6 +19,7 @@ else switch (native_arch) { .riscv32, .riscv32be, .riscv64, .riscv64be => Riscv, .ve => Ve, .s390x => S390x, + .x86_16 => X86_16, .x86 => X86, .x86_64 => X86_64, else => noreturn, @@ -1350,6 +1351,46 @@ const Ve = extern struct { } }; +const X86_16 = struct { + pub const Register = enum { + // zig fmt: off + sp, bp, ss, + ip, cs, + // zig fmt: on + }; + + regs: std.enums.EnumArray(Register, u16), + + pub inline fn current() X86_16 { + var ctx: X86_16 = undefined; + asm volatile ( + \\ movw %%sp, 0x00(%%di) + \\ movw %%bp, 0x02(%%di) + \\ movw %%ss, 0x04(%%di) + \\ pushw %%cs + \\ call 1f + \\1: + \\ popw 0x06(%%di) + \\ popw 0x08(%%di) + : + : [gprs] "{di}" (&ctx.regs.values), + : .{ .memory = true }); + return ctx; + } + + // NOTE: There doesn't seem to be any standard for DWARF x86-16 so we'll just reuse the ones for x86. + pub fn dwarfRegisterBytes(ctx: *X86_16, register_num: u16) DwarfRegisterError![]u8 { + switch (register_num) { + 4 => return @ptrCast(ctx.regs.getPtr(.sp)), + 5 => return @ptrCast(ctx.regs.getPtr(.bp)), + 6 => return @ptrCast(ctx.regs.getPtr(.ip)), + 41 => return @ptrCast(ctx.regs.getPtr(.cs)), + 42 => return @ptrCast(ctx.regs.getPtr(.ss)), + else => return error.InvalidRegister, + } + } +}; + const X86 = struct { /// The first 8 registers here intentionally match the order of registers in the x86 instruction /// encoding. This order is inherited by the PUSHA instruction and the DWARF register mappings,