Commit ef4f6e6c05

GasInfinity <me@gasinfinity.dev>
2025-10-29 14:35:33
feat: add `x86_16` debug `cpu_context`
1 parent fca748f
Changed files (1)
lib
std
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,