| 1 | /// Register state for the native architecture, used by `std.debug` for stack unwinding. |
| 2 | /// `noreturn` if there is no implementation for the native architecture. |
| 3 | /// This can be overriden by exposing a declaration `root.debug.CpuContext`. |
| 4 | pub const Native = if (@hasDecl(root, "debug") and @hasDecl(root.debug, "CpuContext")) |
| 5 | root.debug.CpuContext |
| 6 | else switch (native_arch) { |
| 7 | .aarch64, .aarch64_be => Aarch64, |
| 8 | .alpha => Alpha, |
| 9 | .arc, .arceb => Arc, |
| 10 | .arm, .armeb, .thumb, .thumbeb => Arm, |
| 11 | .csky => Csky, |
| 12 | .hexagon => Hexagon, |
| 13 | .kvx => Kvx, |
| 14 | .lanai => Lanai, |
| 15 | .loongarch32, .loongarch64 => LoongArch, |
| 16 | .m68k => M68k, |
| 17 | .m88k => M88k, |
| 18 | .mips, .mipsel, .mips64, .mips64el => Mips, |
| 19 | .or1k => Or1k, |
| 20 | .powerpc, .powerpcle, .powerpc64, .powerpc64le => Powerpc, |
| 21 | .sparc, .sparc64 => Sparc, |
| 22 | .riscv32, .riscv32be, .riscv64, .riscv64be => Riscv, |
| 23 | .ve => Ve, |
| 24 | .s390x => S390x, |
| 25 | .x86_16 => X86_16, |
| 26 | .x86 => X86, |
| 27 | .x86_64 => X86_64, |
| 28 | else => noreturn, |
| 29 | }; |
| 30 | |
| 31 | pub const DwarfRegisterError = error{ |
| 32 | InvalidRegister, |
| 33 | UnsupportedRegister, |
| 34 | }; |
| 35 | |
| 36 | pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native { |
| 37 | if (signal_ucontext_t == void) return null; |
| 38 | |
| 39 | // In general, we include the hardwired zero register in the context if applicable. |
| 40 | const uc: *const signal_ucontext_t = @ptrCast(@alignCast(ctx_ptr)); |
| 41 | |
| 42 | // Deal with some special cases first. |
| 43 | if (native_arch.isArc() and native_os == .linux) { |
| 44 | var native: Native = .{ |
| 45 | .r = [_]u32{ uc.mcontext.r31, uc.mcontext.r30, 0, uc.mcontext.r28 } ++ |
| 46 | uc.mcontext.r27_26 ++ |
| 47 | uc.mcontext.r25_13 ++ |
| 48 | uc.mcontext.r12_0, |
| 49 | .pcl = uc.mcontext.pcl, |
| 50 | }; |
| 51 | |
| 52 | // I have no idea why the kernel is storing these registers in such a bizarre order... |
| 53 | std.mem.reverse(u32, native.r[0..]); |
| 54 | |
| 55 | return native; |
| 56 | } else if (native_arch == .loongarch32 and native_os == .linux) { |
| 57 | // The 32-bit kABI (added later) kept the 64-bit layout. |
| 58 | return .{ |
| 59 | .r = s: { |
| 60 | var regs: [32]LoongArch.Gpr = undefined; |
| 61 | for (uc.mcontext.r, 0..) |r, i| regs[i] = @truncate(r); |
| 62 | break :s regs; |
| 63 | }, |
| 64 | .pc = @truncate(uc.mcontext.pc), |
| 65 | }; |
| 66 | } else if (native_arch == .m88k and native_os == .openbsd) { |
| 67 | // OpenBSD makes no effort to clear the V and E bits of the SXIP register when presenting it |
| 68 | // to user space, so we need to do that here. |
| 69 | return .{ |
| 70 | .r = uc.mcontext.r, |
| 71 | .xip = uc.mcontext.xip & ~@as(u32, 0b11), |
| 72 | }; |
| 73 | } else if (native_arch.isMIPS32() and native_os == .linux) { |
| 74 | // The O32 kABI uses 64-bit fields for some reason. |
| 75 | return .{ |
| 76 | .r = s: { |
| 77 | var regs: [32]Mips.Gpr = undefined; |
| 78 | for (uc.mcontext.r, 0..) |r, i| regs[i] = @truncate(r); |
| 79 | break :s regs; |
| 80 | }, |
| 81 | .pc = @truncate(uc.mcontext.pc), |
| 82 | }; |
| 83 | } else if (native_arch.isSPARC() and native_os == .linux) { |
| 84 | const SparcStackFrame = extern struct { |
| 85 | l: [8]usize, |
| 86 | i: [8]usize, |
| 87 | _x: [8]usize, |
| 88 | }; |
| 89 | |
| 90 | // When invoking a signal handler, the kernel builds an `rt_signal_frame` structure on the |
| 91 | // stack and passes a pointer to its `info` field to the signal handler. This implies that |
| 92 | // prior to said `info` field, we will find the `ss` field which, among other things, |
| 93 | // contains the incoming and local registers of the interrupted code. |
| 94 | const frame = @as(*const SparcStackFrame, @ptrFromInt(@as(usize, @intFromPtr(ctx_ptr)) - @sizeOf(SparcStackFrame))); |
| 95 | |
| 96 | return .{ |
| 97 | .g = uc.mcontext.g, |
| 98 | .o = uc.mcontext.o, |
| 99 | .l = frame.l, |
| 100 | .i = frame.i, |
| 101 | .pc = uc.mcontext.pc, |
| 102 | }; |
| 103 | } |
| 104 | |
| 105 | // Only unified conversions from here. |
| 106 | return switch (native_arch) { |
| 107 | .arm, .armeb, .thumb, .thumbeb => .{ |
| 108 | .r = uc.mcontext.r ++ [_]u32{uc.mcontext.pc}, |
| 109 | }, |
| 110 | .aarch64, .aarch64_be => .{ |
| 111 | .x = uc.mcontext.x ++ [_]u64{uc.mcontext.lr}, |
| 112 | .sp = uc.mcontext.sp, |
| 113 | .pc = uc.mcontext.pc, |
| 114 | }, |
| 115 | .alpha => .{ |
| 116 | .r = uc.mcontext.r, |
| 117 | .pc = uc.mcontext.pc, |
| 118 | }, |
| 119 | .csky => .{ |
| 120 | .r = uc.mcontext.r0_13 ++ |
| 121 | [_]u32{ uc.mcontext.r14, uc.mcontext.r15 } ++ |
| 122 | uc.mcontext.r16_30 ++ |
| 123 | [_]u32{uc.mcontext.r31}, |
| 124 | .pc = uc.mcontext.pc, |
| 125 | }, |
| 126 | .hexagon, .loongarch32, .loongarch64, .mips, .mipsel, .mips64, .mips64el, .or1k => .{ |
| 127 | .r = uc.mcontext.r, |
| 128 | .pc = uc.mcontext.pc, |
| 129 | }, |
| 130 | .m68k => .{ |
| 131 | .d = uc.mcontext.d, |
| 132 | .a = uc.mcontext.a, |
| 133 | .pc = uc.mcontext.pc, |
| 134 | }, |
| 135 | .powerpc, .powerpcle, .powerpc64, .powerpc64le => .{ |
| 136 | .r = uc.mcontext.r, |
| 137 | .pc = uc.mcontext.pc, |
| 138 | .lr = uc.mcontext.lr, |
| 139 | }, |
| 140 | .riscv32, .riscv32be, .riscv64, .riscv64be => .{ |
| 141 | // You can thank FreeBSD and OpenBSD for this silliness; they decided to be cute and |
| 142 | // group the registers by ABI mnemonic rather than register number. |
| 143 | .x = [_]Riscv.Gpr{0} ++ |
| 144 | uc.mcontext.ra_sp_gp_tp ++ |
| 145 | uc.mcontext.t0_2 ++ |
| 146 | uc.mcontext.s0_1 ++ |
| 147 | uc.mcontext.a ++ |
| 148 | uc.mcontext.s2_11 ++ |
| 149 | uc.mcontext.t3_6, |
| 150 | .pc = uc.mcontext.pc, |
| 151 | }, |
| 152 | .s390x => .{ |
| 153 | .r = uc.mcontext.r, |
| 154 | .psw = .{ |
| 155 | .mask = uc.mcontext.psw.mask, |
| 156 | .addr = uc.mcontext.psw.addr, |
| 157 | }, |
| 158 | }, |
| 159 | .x86 => .{ .gprs = .init(.{ |
| 160 | .eax = uc.mcontext.eax, |
| 161 | .ecx = uc.mcontext.ecx, |
| 162 | .edx = uc.mcontext.edx, |
| 163 | .ebx = uc.mcontext.ebx, |
| 164 | .esp = uc.mcontext.esp, |
| 165 | .ebp = uc.mcontext.ebp, |
| 166 | .esi = uc.mcontext.esi, |
| 167 | .edi = uc.mcontext.edi, |
| 168 | .eip = uc.mcontext.eip, |
| 169 | }) }, |
| 170 | .x86_64 => .{ .gprs = .init(.{ |
| 171 | .rax = uc.mcontext.rax, |
| 172 | .rdx = uc.mcontext.rdx, |
| 173 | .rcx = uc.mcontext.rcx, |
| 174 | .rbx = uc.mcontext.rbx, |
| 175 | .rsi = uc.mcontext.rsi, |
| 176 | .rdi = uc.mcontext.rdi, |
| 177 | .rbp = uc.mcontext.rbp, |
| 178 | .rsp = uc.mcontext.rsp, |
| 179 | .r8 = uc.mcontext.r8, |
| 180 | .r9 = uc.mcontext.r9, |
| 181 | .r10 = uc.mcontext.r10, |
| 182 | .r11 = uc.mcontext.r11, |
| 183 | .r12 = uc.mcontext.r12, |
| 184 | .r13 = uc.mcontext.r13, |
| 185 | .r14 = uc.mcontext.r14, |
| 186 | .r15 = uc.mcontext.r15, |
| 187 | .rip = uc.mcontext.rip, |
| 188 | }) }, |
| 189 | else => comptime unreachable, |
| 190 | }; |
| 191 | } |
| 192 | |
| 193 | pub fn fromWindowsContext(ctx: *const std.os.windows.CONTEXT) Native { |
| 194 | return switch (native_arch) { |
| 195 | .x86 => .{ .gprs = .init(.{ |
| 196 | .eax = ctx.Eax, |
| 197 | .ecx = ctx.Ecx, |
| 198 | .edx = ctx.Edx, |
| 199 | .ebx = ctx.Ebx, |
| 200 | .esp = ctx.Esp, |
| 201 | .ebp = ctx.Ebp, |
| 202 | .esi = ctx.Esi, |
| 203 | .edi = ctx.Edi, |
| 204 | .eip = ctx.Eip, |
| 205 | }) }, |
| 206 | .x86_64 => .{ .gprs = .init(.{ |
| 207 | .rax = ctx.Rax, |
| 208 | .rdx = ctx.Rdx, |
| 209 | .rcx = ctx.Rcx, |
| 210 | .rbx = ctx.Rbx, |
| 211 | .rsi = ctx.Rsi, |
| 212 | .rdi = ctx.Rdi, |
| 213 | .rbp = ctx.Rbp, |
| 214 | .rsp = ctx.Rsp, |
| 215 | .r8 = ctx.R8, |
| 216 | .r9 = ctx.R9, |
| 217 | .r10 = ctx.R10, |
| 218 | .r11 = ctx.R11, |
| 219 | .r12 = ctx.R12, |
| 220 | .r13 = ctx.R13, |
| 221 | .r14 = ctx.R14, |
| 222 | .r15 = ctx.R15, |
| 223 | .rip = ctx.Rip, |
| 224 | }) }, |
| 225 | .aarch64 => .{ |
| 226 | .x = ctx.DUMMYUNIONNAME.X[0..31].*, |
| 227 | .sp = ctx.Sp, |
| 228 | .pc = ctx.Pc, |
| 229 | }, |
| 230 | .thumb => .{ .r = .{ |
| 231 | ctx.R0, ctx.R1, ctx.R2, ctx.R3, |
| 232 | ctx.R4, ctx.R5, ctx.R6, ctx.R7, |
| 233 | ctx.R8, ctx.R9, ctx.R10, ctx.R11, |
| 234 | ctx.R12, ctx.Sp, ctx.Lr, ctx.Pc, |
| 235 | } }, |
| 236 | else => comptime unreachable, |
| 237 | }; |
| 238 | } |
| 239 | |
| 240 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| 241 | const Aarch64 = extern struct { |
| 242 | /// The numbered general-purpose registers X0 - X30. |
| 243 | x: [31]Gpr, |
| 244 | sp: Gpr, |
| 245 | pc: Gpr, |
| 246 | |
| 247 | pub const Gpr = u64; |
| 248 | |
| 249 | pub inline fn current() Aarch64 { |
| 250 | var ctx: Aarch64 = undefined; |
| 251 | asm volatile ( |
| 252 | \\ stp x0, x1, [x0, #0x000] |
| 253 | \\ stp x2, x3, [x0, #0x010] |
| 254 | \\ stp x4, x5, [x0, #0x020] |
| 255 | \\ stp x6, x7, [x0, #0x030] |
| 256 | \\ stp x8, x9, [x0, #0x040] |
| 257 | \\ stp x10, x11, [x0, #0x050] |
| 258 | \\ stp x12, x13, [x0, #0x060] |
| 259 | \\ stp x14, x15, [x0, #0x070] |
| 260 | \\ stp x16, x17, [x0, #0x080] |
| 261 | \\ stp x18, x19, [x0, #0x090] |
| 262 | \\ stp x20, x21, [x0, #0x0a0] |
| 263 | \\ stp x22, x23, [x0, #0x0b0] |
| 264 | \\ stp x24, x25, [x0, #0x0c0] |
| 265 | \\ stp x26, x27, [x0, #0x0d0] |
| 266 | \\ stp x28, x29, [x0, #0x0e0] |
| 267 | \\ str x30, [x0, #0x0f0] |
| 268 | \\ mov x1, sp |
| 269 | \\ str x1, [x0, #0x0f8] |
| 270 | \\ adr x1, . |
| 271 | \\ str x1, [x0, #0x100] |
| 272 | : |
| 273 | : [ctx] "{x0}" (&ctx), |
| 274 | : .{ .x1 = true, .memory = true }); |
| 275 | return ctx; |
| 276 | } |
| 277 | |
| 278 | pub fn getFp(ctx: *const Aarch64) usize { |
| 279 | return ctx.x[29]; |
| 280 | } |
| 281 | pub fn getPc(ctx: *const Aarch64) usize { |
| 282 | return ctx.pc; |
| 283 | } |
| 284 | |
| 285 | pub fn dwarfRegisterBytes(ctx: *Aarch64, register_num: u16) DwarfRegisterError![]u8 { |
| 286 | // DWARF for the Arm(r) 64-bit Architecture (AArch64) § 4.1 "DWARF register names" |
| 287 | switch (register_num) { |
| 288 | 0...30 => return @ptrCast(&ctx.x[register_num]), |
| 289 | 31 => return @ptrCast(&ctx.sp), |
| 290 | 32 => return @ptrCast(&ctx.pc), |
| 291 | |
| 292 | 33 => return error.UnsupportedRegister, // ELR_mode |
| 293 | 34 => return error.UnsupportedRegister, // RA_SIGN_STATE |
| 294 | 35 => return error.UnsupportedRegister, // TPIDRRO_ELO |
| 295 | 36 => return error.UnsupportedRegister, // TPIDR_ELO |
| 296 | 37 => return error.UnsupportedRegister, // TPIDR_EL1 |
| 297 | 38 => return error.UnsupportedRegister, // TPIDR_EL2 |
| 298 | 39 => return error.UnsupportedRegister, // TPIDR_EL3 |
| 299 | 40...45 => return error.UnsupportedRegister, // Reserved |
| 300 | 46 => return error.UnsupportedRegister, // VG |
| 301 | 47 => return error.UnsupportedRegister, // FFR |
| 302 | 48...63 => return error.UnsupportedRegister, // P0 - P15 |
| 303 | 64...95 => return error.UnsupportedRegister, // V0 - V31 |
| 304 | 96...127 => return error.UnsupportedRegister, // Z0 - Z31 |
| 305 | |
| 306 | else => return error.InvalidRegister, |
| 307 | } |
| 308 | } |
| 309 | }; |
| 310 | |
| 311 | const Alpha = extern struct { |
| 312 | /// The numbered general-purpose registers R0 - R31. |
| 313 | r: [32]Gpr, |
| 314 | pc: Gpr, |
| 315 | |
| 316 | pub const Gpr = u64; |
| 317 | |
| 318 | pub inline fn current() Alpha { |
| 319 | var ctx: Alpha = undefined; |
| 320 | asm volatile ( |
| 321 | \\ stq $0 , 0x000($0) |
| 322 | \\ stq $1 , 0x008($0) |
| 323 | \\ stq $2 , 0x010($0) |
| 324 | \\ stq $3 , 0x018($0) |
| 325 | \\ stq $4 , 0x020($0) |
| 326 | \\ stq $5 , 0x028($0) |
| 327 | \\ stq $6 , 0x030($0) |
| 328 | \\ stq $7 , 0x038($0) |
| 329 | \\ stq $8 , 0x040($0) |
| 330 | \\ stq $9 , 0x048($0) |
| 331 | \\ stq $10, 0x050($0) |
| 332 | \\ stq $11, 0x058($0) |
| 333 | \\ stq $12, 0x060($0) |
| 334 | \\ stq $13, 0x068($0) |
| 335 | \\ stq $14, 0x070($0) |
| 336 | \\ stq $15, 0x078($0) |
| 337 | \\ stq $16, 0x080($0) |
| 338 | \\ stq $17, 0x088($0) |
| 339 | \\ stq $18, 0x090($0) |
| 340 | \\ stq $19, 0x098($0) |
| 341 | \\ stq $20, 0x0a0($0) |
| 342 | \\ stq $21, 0x0a8($0) |
| 343 | \\ stq $22, 0x0b0($0) |
| 344 | \\ stq $23, 0x0b8($0) |
| 345 | \\ stq $24, 0x0c0($0) |
| 346 | \\ stq $25, 0x0c8($0) |
| 347 | \\ stq $26, 0x0d0($0) |
| 348 | \\ stq $27, 0x0d8($0) |
| 349 | \\ stq $28, 0x0e0($0) |
| 350 | \\ stq $29, 0x0e8($0) |
| 351 | \\ stq $30, 0x0f0($0) |
| 352 | \\ stq $31, 0x0f8($0) |
| 353 | \\ |
| 354 | \\ br $1, 1f |
| 355 | \\1: |
| 356 | \\ stq $1, 0x100($0) |
| 357 | : |
| 358 | : [ctx] "{$0}" (&ctx), |
| 359 | : .{ .r1 = true, .memory = true }); |
| 360 | return ctx; |
| 361 | } |
| 362 | |
| 363 | pub fn getFp(ctx: *const Alpha) usize { |
| 364 | return ctx.r[15]; |
| 365 | } |
| 366 | pub fn getPc(ctx: *const Alpha) usize { |
| 367 | return ctx.pc; |
| 368 | } |
| 369 | |
| 370 | pub fn dwarfRegisterBytes(ctx: *Alpha, register_num: u16) DwarfRegisterError![]u8 { |
| 371 | switch (register_num) { |
| 372 | 0...31 => return @ptrCast(&ctx.r[register_num]), |
| 373 | 64 => return @ptrCast(&ctx.pc), |
| 374 | |
| 375 | 32...63 => return error.UnsupportedRegister, // f0 - f31 |
| 376 | 66 => return error.UnsupportedRegister, // uniq |
| 377 | |
| 378 | else => return error.InvalidRegister, |
| 379 | } |
| 380 | } |
| 381 | }; |
| 382 | |
| 383 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| 384 | const Arc = extern struct { |
| 385 | /// The numbered general-purpose registers r0 - r31. |
| 386 | r: [32]Gpr, |
| 387 | pcl: Gpr, |
| 388 | |
| 389 | pub const Gpr = u32; |
| 390 | |
| 391 | pub inline fn current() Arc { |
| 392 | var ctx: Arc = undefined; |
| 393 | asm volatile ( |
| 394 | \\ st r0, [r8, 0] |
| 395 | \\ st r1, [r8, 4] |
| 396 | \\ st r2, [r8, 8] |
| 397 | \\ st r3, [r8, 12] |
| 398 | \\ st r4, [r8, 16] |
| 399 | \\ st r5, [r8, 20] |
| 400 | \\ st r6, [r8, 24] |
| 401 | \\ st r7, [r8, 28] |
| 402 | \\ st r8, [r8, 32] |
| 403 | \\ st r9, [r8, 36] |
| 404 | \\ st r10, [r8, 40] |
| 405 | \\ st r11, [r8, 44] |
| 406 | \\ st r12, [r8, 48] |
| 407 | \\ st r13, [r8, 52] |
| 408 | \\ st r14, [r8, 56] |
| 409 | \\ st r15, [r8, 60] |
| 410 | \\ st r16, [r8, 64] |
| 411 | \\ st r17, [r8, 68] |
| 412 | \\ st r18, [r8, 72] |
| 413 | \\ st r19, [r8, 76] |
| 414 | \\ st r20, [r8, 80] |
| 415 | \\ st r21, [r8, 84] |
| 416 | \\ st r22, [r8, 88] |
| 417 | \\ st r23, [r8, 92] |
| 418 | \\ st r24, [r8, 96] |
| 419 | \\ st r25, [r8, 100] |
| 420 | \\ st r26, [r8, 104] |
| 421 | \\ st r27, [r8, 108] |
| 422 | \\ st r28, [r8, 112] |
| 423 | \\ st r29, [r8, 116] |
| 424 | \\ st r30, [r8, 120] |
| 425 | \\ st r31, [r8, 124] |
| 426 | \\ st pcl, [r8, 128] |
| 427 | : |
| 428 | : [ctx] "{r8}" (&ctx), |
| 429 | : .{ .memory = true }); |
| 430 | return ctx; |
| 431 | } |
| 432 | |
| 433 | pub fn getFp(ctx: *const Arc) usize { |
| 434 | return ctx.r[27]; |
| 435 | } |
| 436 | pub fn getPc(ctx: *const Arc) usize { |
| 437 | return ctx.pcl; |
| 438 | } |
| 439 | |
| 440 | pub fn dwarfRegisterBytes(ctx: *Arc, register_num: u16) DwarfRegisterError![]u8 { |
| 441 | switch (register_num) { |
| 442 | 0...31 => return @ptrCast(&ctx.r[register_num]), |
| 443 | 160 => return @ptrCast(&ctx.pcl), |
| 444 | |
| 445 | 32...57 => return error.UnsupportedRegister, // Extension Core Registers |
| 446 | 58...127 => return error.UnsupportedRegister, // Reserved |
| 447 | 128...159 => return error.UnsupportedRegister, // f0 - f31 |
| 448 | |
| 449 | else => return error.InvalidRegister, |
| 450 | } |
| 451 | } |
| 452 | }; |
| 453 | |
| 454 | const Arm = struct { |
| 455 | /// The numbered general-purpose registers R0 - R15. |
| 456 | r: [16]Gpr, |
| 457 | |
| 458 | pub const Gpr = u32; |
| 459 | |
| 460 | pub inline fn current() Arm { |
| 461 | var ctx: Arm = undefined; |
| 462 | asm volatile ( |
| 463 | \\ // For compatibility with Thumb, we can't write r13 (sp) or r15 (pc) with stm. |
| 464 | \\ stm r0, {r0-r12} |
| 465 | \\ str r13, [r0, #0x34] |
| 466 | \\ str r14, [r0, #0x38] |
| 467 | \\ mov r1, pc |
| 468 | \\ str r1, [r0, #0x3c] |
| 469 | : |
| 470 | : [r] "{r0}" (&ctx.r), |
| 471 | : .{ .r1 = true, .memory = true }); |
| 472 | return ctx; |
| 473 | } |
| 474 | |
| 475 | pub fn getFp(ctx: *const Arm) usize { |
| 476 | return ctx.r[11]; |
| 477 | } |
| 478 | pub fn getPc(ctx: *const Arm) usize { |
| 479 | return ctx.r[15]; |
| 480 | } |
| 481 | |
| 482 | pub fn dwarfRegisterBytes(ctx: *Arm, register_num: u16) DwarfRegisterError![]u8 { |
| 483 | // DWARF for the Arm(r) Architecture § 4.1 "DWARF register names" |
| 484 | switch (register_num) { |
| 485 | 0...15 => return @ptrCast(&ctx.r[register_num]), |
| 486 | |
| 487 | 64...95 => return error.UnsupportedRegister, // S0 - S31 |
| 488 | 96...103 => return error.UnsupportedRegister, // F0 - F7 |
| 489 | 104...111 => return error.UnsupportedRegister, // wCGR0 - wCGR7, or ACC0 - ACC7 |
| 490 | 112...127 => return error.UnsupportedRegister, // wR0 - wR15 |
| 491 | 128 => return error.UnsupportedRegister, // SPSR |
| 492 | 129 => return error.UnsupportedRegister, // SPSR_FIQ |
| 493 | 130 => return error.UnsupportedRegister, // SPSR_IRQ |
| 494 | 131 => return error.UnsupportedRegister, // SPSR_ABT |
| 495 | 132 => return error.UnsupportedRegister, // SPSR_UND |
| 496 | 133 => return error.UnsupportedRegister, // SPSR_SVC |
| 497 | 134...142 => return error.UnsupportedRegister, // Reserved |
| 498 | 143 => return error.UnsupportedRegister, // RA_AUTH_CODE |
| 499 | 144...150 => return error.UnsupportedRegister, // R8_USR - R14_USR |
| 500 | 151...157 => return error.UnsupportedRegister, // R8_FIQ - R14_FIQ |
| 501 | 158...159 => return error.UnsupportedRegister, // R13_IRQ - R14_IRQ |
| 502 | 160...161 => return error.UnsupportedRegister, // R13_ABT - R14_ABT |
| 503 | 162...163 => return error.UnsupportedRegister, // R13_UND - R14_UND |
| 504 | 164...165 => return error.UnsupportedRegister, // R13_SVC - R14_SVC |
| 505 | 166...191 => return error.UnsupportedRegister, // Reserved |
| 506 | 192...199 => return error.UnsupportedRegister, // wC0 - wC7 |
| 507 | 200...255 => return error.UnsupportedRegister, // Reserved |
| 508 | 256...287 => return error.UnsupportedRegister, // D0 - D31 |
| 509 | 288...319 => return error.UnsupportedRegister, // Reserved for FP/NEON |
| 510 | 320 => return error.UnsupportedRegister, // TPIDRURO |
| 511 | 321 => return error.UnsupportedRegister, // TPIDRURW |
| 512 | 322 => return error.UnsupportedRegister, // TPIDPR |
| 513 | 323 => return error.UnsupportedRegister, // HTPIDPR |
| 514 | 324...8191 => return error.UnsupportedRegister, // Reserved |
| 515 | 8192...16383 => return error.UnsupportedRegister, // Unspecified vendor co-processor register |
| 516 | |
| 517 | else => return error.InvalidRegister, |
| 518 | } |
| 519 | } |
| 520 | }; |
| 521 | |
| 522 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| 523 | const Csky = extern struct { |
| 524 | /// The numbered general-purpose registers r0 - r31. |
| 525 | r: [32]Gpr, |
| 526 | pc: Gpr, |
| 527 | |
| 528 | pub const Gpr = u32; |
| 529 | |
| 530 | pub inline fn current() Csky { |
| 531 | var ctx: Csky = undefined; |
| 532 | asm volatile ( |
| 533 | \\ stm r0-r31, (t0) |
| 534 | \\ grs t1, 1f |
| 535 | \\1: |
| 536 | \\ st32.w t1, (t0, 128) |
| 537 | : |
| 538 | : [ctx] "{r12}" (&ctx), |
| 539 | : .{ .r13 = true, .memory = true }); |
| 540 | return ctx; |
| 541 | } |
| 542 | |
| 543 | pub fn getFp(ctx: *const Csky) usize { |
| 544 | return ctx.r[14]; |
| 545 | } |
| 546 | pub fn getPc(ctx: *const Csky) usize { |
| 547 | return ctx.pc; |
| 548 | } |
| 549 | |
| 550 | pub fn dwarfRegisterBytes(ctx: *Csky, register_num: u16) DwarfRegisterError![]u8 { |
| 551 | switch (register_num) { |
| 552 | 0...31 => return @ptrCast(&ctx.r[register_num]), |
| 553 | 64 => return @ptrCast(&ctx.pc), |
| 554 | |
| 555 | 32...63 => return error.UnsupportedRegister, // f0 - f31 |
| 556 | |
| 557 | else => return error.InvalidRegister, |
| 558 | } |
| 559 | } |
| 560 | }; |
| 561 | |
| 562 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| 563 | const Hexagon = extern struct { |
| 564 | /// The numbered general-purpose registers r0 - r31. |
| 565 | r: [32]Gpr, |
| 566 | pc: Gpr, |
| 567 | |
| 568 | pub const Gpr = u32; |
| 569 | |
| 570 | pub inline fn current() Hexagon { |
| 571 | var ctx: Hexagon = undefined; |
| 572 | asm volatile ( |
| 573 | \\ memw(r0 + #0) = r0 |
| 574 | \\ memw(r0 + #4) = r1 |
| 575 | \\ memw(r0 + #8) = r2 |
| 576 | \\ memw(r0 + #12) = r3 |
| 577 | \\ memw(r0 + #16) = r4 |
| 578 | \\ memw(r0 + #20) = r5 |
| 579 | \\ memw(r0 + #24) = r6 |
| 580 | \\ memw(r0 + #28) = r7 |
| 581 | \\ memw(r0 + #32) = r8 |
| 582 | \\ memw(r0 + #36) = r9 |
| 583 | \\ memw(r0 + #40) = r10 |
| 584 | \\ memw(r0 + #44) = r11 |
| 585 | \\ memw(r0 + #48) = r12 |
| 586 | \\ memw(r0 + #52) = r13 |
| 587 | \\ memw(r0 + #56) = r14 |
| 588 | \\ memw(r0 + #60) = r15 |
| 589 | \\ memw(r0 + #64) = r16 |
| 590 | \\ memw(r0 + #68) = r17 |
| 591 | \\ memw(r0 + #72) = r18 |
| 592 | \\ memw(r0 + #76) = r19 |
| 593 | \\ memw(r0 + #80) = r20 |
| 594 | \\ memw(r0 + #84) = r21 |
| 595 | \\ memw(r0 + #88) = r22 |
| 596 | \\ memw(r0 + #92) = r23 |
| 597 | \\ memw(r0 + #96) = r24 |
| 598 | \\ memw(r0 + #100) = r25 |
| 599 | \\ memw(r0 + #104) = r26 |
| 600 | \\ memw(r0 + #108) = r27 |
| 601 | \\ memw(r0 + #112) = r28 |
| 602 | \\ memw(r0 + #116) = r29 |
| 603 | \\ memw(r0 + #120) = r30 |
| 604 | \\ memw(r0 + #124) = r31 |
| 605 | \\ r1 = pc |
| 606 | \\ memw(r0 + #128) = r1 |
| 607 | : |
| 608 | : [ctx] "{r0}" (&ctx), |
| 609 | : .{ .r1 = true, .memory = true }); |
| 610 | return ctx; |
| 611 | } |
| 612 | |
| 613 | pub fn getFp(ctx: *const Hexagon) usize { |
| 614 | return ctx.r[30]; |
| 615 | } |
| 616 | pub fn getPc(ctx: *const Hexagon) usize { |
| 617 | return ctx.pc; |
| 618 | } |
| 619 | |
| 620 | pub fn dwarfRegisterBytes(ctx: *Hexagon, register_num: u16) DwarfRegisterError![]u8 { |
| 621 | // Sourced from LLVM's HexagonRegisterInfo.td, which disagrees with LLDB... |
| 622 | switch (register_num) { |
| 623 | 0...31 => return @ptrCast(&ctx.r[register_num]), |
| 624 | 76 => return @ptrCast(&ctx.pc), |
| 625 | |
| 626 | // This is probably covering some numbers that aren't actually mapped, but seriously, |
| 627 | // look at that file. I really can't be bothered to make it more precise. |
| 628 | 32...75 => return error.UnsupportedRegister, |
| 629 | 77...259 => return error.UnsupportedRegister, |
| 630 | // 999999...1000030 => return error.UnsupportedRegister, |
| 631 | // 9999999...10000030 => return error.UnsupportedRegister, |
| 632 | |
| 633 | else => return error.InvalidRegister, |
| 634 | } |
| 635 | } |
| 636 | }; |
| 637 | |
| 638 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| 639 | const Kvx = extern struct { |
| 640 | r: [64]Gpr, |
| 641 | pc: Gpr, |
| 642 | ra: Gpr, |
| 643 | |
| 644 | pub const Gpr = u64; |
| 645 | |
| 646 | pub inline fn current() Kvx { |
| 647 | var ctx: Kvx = undefined; |
| 648 | asm volatile ( |
| 649 | \\ so (0)[$r32] = $r0r1r2r3 |
| 650 | \\ ;; |
| 651 | \\ so (32)[$r32] = $r4r5r6r7 |
| 652 | \\ ;; |
| 653 | \\ so (64)[$r32] = $r8r9r10r11 |
| 654 | \\ ;; |
| 655 | \\ so (96)[$r32] = $r12r13r14r15 |
| 656 | \\ ;; |
| 657 | \\ so (128)[$r32] = $r16r17r18r19 |
| 658 | \\ ;; |
| 659 | \\ so (160)[$r32] = $r20r21r22r23 |
| 660 | \\ ;; |
| 661 | \\ so (192)[$r32] = $r24r25r26r27 |
| 662 | \\ ;; |
| 663 | \\ so (224)[$r32] = $r28r29r30r31 |
| 664 | \\ ;; |
| 665 | \\ so (256)[$r32] = $r32r33r34r35 |
| 666 | \\ ;; |
| 667 | \\ so (288)[$r32] = $r36r37r38r39 |
| 668 | \\ ;; |
| 669 | \\ so (320)[$r32] = $r40r41r42r43 |
| 670 | \\ ;; |
| 671 | \\ so (352)[$r32] = $r44r45r46r47 |
| 672 | \\ ;; |
| 673 | \\ so (384)[$r32] = $r48r49r50r51 |
| 674 | \\ ;; |
| 675 | \\ so (416)[$r32] = $r52r53r54r55 |
| 676 | \\ ;; |
| 677 | \\ so (448)[$r32] = $r56r57r58r59 |
| 678 | \\ get $r34 = $pc |
| 679 | \\ ;; |
| 680 | \\ so (480)[$r32] = $r60r61r62r63 |
| 681 | \\ get $r35 = $ra |
| 682 | \\ ;; |
| 683 | \\ sq (512)[$r32] = $r34r35 |
| 684 | : |
| 685 | : [ctx] "{r32}" (&ctx), |
| 686 | : .{ .r34 = true, .r35 = true, .memory = true }); |
| 687 | return ctx; |
| 688 | } |
| 689 | |
| 690 | pub fn getFp(ctx: *const Kvx) usize { |
| 691 | return ctx.r[14]; |
| 692 | } |
| 693 | pub fn getPc(ctx: *const Kvx) usize { |
| 694 | return ctx.pc; |
| 695 | } |
| 696 | |
| 697 | pub fn dwarfRegisterBytes(ctx: *Kvx, register_num: u16) DwarfRegisterError![]u8 { |
| 698 | switch (register_num) { |
| 699 | 0...63 => return @ptrCast(&ctx.r[register_num]), |
| 700 | 64 => return @ptrCast(&ctx.pc), |
| 701 | 67 => return @ptrCast(&ctx.ra), |
| 702 | |
| 703 | 65...66 => return error.UnsupportedRegister, // SFRs |
| 704 | 68...255 => return error.UnsupportedRegister, // SFRs |
| 705 | 256...767 => return error.UnsupportedRegister, // XCRs |
| 706 | |
| 707 | else => return error.InvalidRegister, |
| 708 | } |
| 709 | } |
| 710 | }; |
| 711 | |
| 712 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| 713 | const Lanai = extern struct { |
| 714 | r: [32]Gpr, |
| 715 | |
| 716 | pub const Gpr = u32; |
| 717 | |
| 718 | pub inline fn current() Lanai { |
| 719 | var ctx: Lanai = undefined; |
| 720 | asm volatile ( |
| 721 | \\ st %%r0, 0[%%r9] |
| 722 | \\ st %%r1, 4[%%r9] |
| 723 | \\ st %%r2, 8[%%r9] |
| 724 | \\ st %%r3, 12[%%r9] |
| 725 | \\ st %%r4, 16[%%r9] |
| 726 | \\ st %%r5, 20[%%r9] |
| 727 | \\ st %%r6, 24[%%r9] |
| 728 | \\ st %%r7, 28[%%r9] |
| 729 | \\ st %%r8, 32[%%r9] |
| 730 | \\ st %%r9, 36[%%r9] |
| 731 | \\ st %%r10, 40[%%r9] |
| 732 | \\ st %%r11, 44[%%r9] |
| 733 | \\ st %%r12, 48[%%r9] |
| 734 | \\ st %%r13, 52[%%r9] |
| 735 | \\ st %%r14, 56[%%r9] |
| 736 | \\ st %%r15, 60[%%r9] |
| 737 | \\ st %%r16, 64[%%r9] |
| 738 | \\ st %%r17, 68[%%r9] |
| 739 | \\ st %%r18, 72[%%r9] |
| 740 | \\ st %%r19, 76[%%r9] |
| 741 | \\ st %%r20, 80[%%r9] |
| 742 | \\ st %%r21, 84[%%r9] |
| 743 | \\ st %%r22, 88[%%r9] |
| 744 | \\ st %%r23, 92[%%r9] |
| 745 | \\ st %%r24, 96[%%r9] |
| 746 | \\ st %%r25, 100[%%r9] |
| 747 | \\ st %%r26, 104[%%r9] |
| 748 | \\ st %%r27, 108[%%r9] |
| 749 | \\ st %%r28, 112[%%r9] |
| 750 | \\ st %%r29, 116[%%r9] |
| 751 | \\ st %%r30, 120[%%r9] |
| 752 | \\ st %%r31, 124[%%r9] |
| 753 | : |
| 754 | : [ctx] "{r9}" (&ctx), |
| 755 | : .{ .memory = true }); |
| 756 | return ctx; |
| 757 | } |
| 758 | |
| 759 | pub fn getFp(ctx: *const Lanai) usize { |
| 760 | return ctx.r[5]; |
| 761 | } |
| 762 | pub fn getPc(ctx: *const Lanai) usize { |
| 763 | return ctx.r[2]; |
| 764 | } |
| 765 | |
| 766 | pub fn dwarfRegisterBytes(ctx: *Lanai, register_num: u16) DwarfRegisterError![]u8 { |
| 767 | switch (register_num) { |
| 768 | 0...31 => return @ptrCast(&ctx.r[register_num]), |
| 769 | |
| 770 | else => return error.InvalidRegister, |
| 771 | } |
| 772 | } |
| 773 | }; |
| 774 | |
| 775 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| 776 | const LoongArch = extern struct { |
| 777 | /// The numbered general-purpose registers r0 - r31. r0 must be zero. |
| 778 | r: [32]Gpr, |
| 779 | pc: Gpr, |
| 780 | |
| 781 | pub const Gpr = if (native_arch == .loongarch64) u64 else u32; |
| 782 | |
| 783 | pub inline fn current() LoongArch { |
| 784 | var ctx: LoongArch = undefined; |
| 785 | asm volatile (if (Gpr == u64) |
| 786 | \\ st.d $zero, $t0, 0 |
| 787 | \\ st.d $ra, $t0, 8 |
| 788 | \\ st.d $tp, $t0, 16 |
| 789 | \\ st.d $sp, $t0, 24 |
| 790 | \\ st.d $a0, $t0, 32 |
| 791 | \\ st.d $a1, $t0, 40 |
| 792 | \\ st.d $a2, $t0, 48 |
| 793 | \\ st.d $a3, $t0, 56 |
| 794 | \\ st.d $a4, $t0, 64 |
| 795 | \\ st.d $a5, $t0, 72 |
| 796 | \\ st.d $a6, $t0, 80 |
| 797 | \\ st.d $a7, $t0, 88 |
| 798 | \\ st.d $t0, $t0, 96 |
| 799 | \\ st.d $t1, $t0, 104 |
| 800 | \\ st.d $t2, $t0, 112 |
| 801 | \\ st.d $t3, $t0, 120 |
| 802 | \\ st.d $t4, $t0, 128 |
| 803 | \\ st.d $t5, $t0, 136 |
| 804 | \\ st.d $t6, $t0, 144 |
| 805 | \\ st.d $t7, $t0, 152 |
| 806 | \\ st.d $t8, $t0, 160 |
| 807 | \\ st.d $r21, $t0, 168 |
| 808 | \\ st.d $fp, $t0, 176 |
| 809 | \\ st.d $s0, $t0, 184 |
| 810 | \\ st.d $s1, $t0, 192 |
| 811 | \\ st.d $s2, $t0, 200 |
| 812 | \\ st.d $s3, $t0, 208 |
| 813 | \\ st.d $s4, $t0, 216 |
| 814 | \\ st.d $s5, $t0, 224 |
| 815 | \\ st.d $s6, $t0, 232 |
| 816 | \\ st.d $s7, $t0, 240 |
| 817 | \\ st.d $s8, $t0, 248 |
| 818 | \\ bl 1f |
| 819 | \\1: |
| 820 | \\ st.d $ra, $t0, 256 |
| 821 | else |
| 822 | \\ st.w $zero, $t0, 0 |
| 823 | \\ st.w $ra, $t0, 4 |
| 824 | \\ st.w $tp, $t0, 8 |
| 825 | \\ st.w $sp, $t0, 12 |
| 826 | \\ st.w $a0, $t0, 16 |
| 827 | \\ st.w $a1, $t0, 20 |
| 828 | \\ st.w $a2, $t0, 24 |
| 829 | \\ st.w $a3, $t0, 28 |
| 830 | \\ st.w $a4, $t0, 32 |
| 831 | \\ st.w $a5, $t0, 36 |
| 832 | \\ st.w $a6, $t0, 40 |
| 833 | \\ st.w $a7, $t0, 44 |
| 834 | \\ st.w $t0, $t0, 48 |
| 835 | \\ st.w $t1, $t0, 52 |
| 836 | \\ st.w $t2, $t0, 56 |
| 837 | \\ st.w $t3, $t0, 60 |
| 838 | \\ st.w $t4, $t0, 64 |
| 839 | \\ st.w $t5, $t0, 68 |
| 840 | \\ st.w $t6, $t0, 72 |
| 841 | \\ st.w $t7, $t0, 76 |
| 842 | \\ st.w $t8, $t0, 80 |
| 843 | \\ st.w $r21, $t0, 84 |
| 844 | \\ st.w $fp, $t0, 88 |
| 845 | \\ st.w $s0, $t0, 92 |
| 846 | \\ st.w $s1, $t0, 96 |
| 847 | \\ st.w $s2, $t0, 100 |
| 848 | \\ st.w $s3, $t0, 104 |
| 849 | \\ st.w $s4, $t0, 108 |
| 850 | \\ st.w $s5, $t0, 112 |
| 851 | \\ st.w $s6, $t0, 116 |
| 852 | \\ st.w $s7, $t0, 120 |
| 853 | \\ st.w $s8, $t0, 124 |
| 854 | \\ bl 1f |
| 855 | \\1: |
| 856 | \\ st.w $ra, $t0, 128 |
| 857 | : |
| 858 | : [ctx] "{$r12}" (&ctx), |
| 859 | : .{ .r1 = true, .memory = true }); |
| 860 | return ctx; |
| 861 | } |
| 862 | |
| 863 | pub fn getFp(ctx: *const LoongArch) usize { |
| 864 | return ctx.r[22]; |
| 865 | } |
| 866 | pub fn getPc(ctx: *const LoongArch) usize { |
| 867 | return ctx.pc; |
| 868 | } |
| 869 | |
| 870 | pub fn dwarfRegisterBytes(ctx: *LoongArch, register_num: u16) DwarfRegisterError![]u8 { |
| 871 | switch (register_num) { |
| 872 | 0...31 => return @ptrCast(&ctx.r[register_num]), |
| 873 | 64 => return @ptrCast(&ctx.pc), |
| 874 | |
| 875 | 32...63 => return error.UnsupportedRegister, // f0 - f31 |
| 876 | |
| 877 | else => return error.InvalidRegister, |
| 878 | } |
| 879 | } |
| 880 | }; |
| 881 | |
| 882 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| 883 | const M68k = extern struct { |
| 884 | /// The numbered data registers d0 - d7. |
| 885 | d: [8]Gpr, |
| 886 | /// The numbered address registers a0 - a7. |
| 887 | a: [8]Gpr, |
| 888 | pc: Gpr, |
| 889 | |
| 890 | pub const Gpr = u32; |
| 891 | |
| 892 | pub inline fn current() M68k { |
| 893 | var ctx: M68k = undefined; |
| 894 | asm volatile ( |
| 895 | \\ movem.l %%d0 - %%a7, (%%a0) |
| 896 | \\ lea.l (%%pc), %%a1 |
| 897 | \\ move.l %%a1, (%%a0, 64) |
| 898 | : |
| 899 | : [ctx] "{a0}" (&ctx), |
| 900 | : .{ .a1 = true, .memory = true }); |
| 901 | return ctx; |
| 902 | } |
| 903 | |
| 904 | pub fn getFp(ctx: *const M68k) usize { |
| 905 | return ctx.a[6]; |
| 906 | } |
| 907 | pub fn getPc(ctx: *const M68k) usize { |
| 908 | return ctx.pc; |
| 909 | } |
| 910 | |
| 911 | pub fn dwarfRegisterBytes(ctx: *M68k, register_num: u16) DwarfRegisterError![]u8 { |
| 912 | switch (register_num) { |
| 913 | 0...7 => return @ptrCast(&ctx.d[register_num]), |
| 914 | 8...15 => return @ptrCast(&ctx.a[register_num - 8]), |
| 915 | 26 => return @ptrCast(&ctx.pc), |
| 916 | |
| 917 | 16...23 => return error.UnsupportedRegister, // fp0 - fp7 |
| 918 | 24...25 => return error.UnsupportedRegister, // Return columns in GCC...? |
| 919 | |
| 920 | else => return error.InvalidRegister, |
| 921 | } |
| 922 | } |
| 923 | }; |
| 924 | |
| 925 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| 926 | const M88k = extern struct { |
| 927 | /// The numbered general-purpose registers r0 - r31. |
| 928 | r: [32]Gpr, |
| 929 | xip: Gpr, |
| 930 | |
| 931 | pub const Gpr = u32; |
| 932 | |
| 933 | pub inline fn current() M88k { |
| 934 | var ctx: M88k = undefined; |
| 935 | asm volatile ( |
| 936 | \\ st %%r0, %%r2, 0 |
| 937 | \\ st %%r1, %%r2, 4 |
| 938 | \\ st %%r2, %%r2, 8 |
| 939 | \\ st %%r3, %%r2, 12 |
| 940 | \\ st %%r4, %%r2, 16 |
| 941 | \\ st %%r5, %%r2, 20 |
| 942 | \\ st %%r6, %%r2, 24 |
| 943 | \\ st %%r7, %%r2, 28 |
| 944 | \\ st %%r8, %%r2, 32 |
| 945 | \\ st %%r9, %%r2, 36 |
| 946 | \\ st %%r10, %%r2, 40 |
| 947 | \\ st %%r11, %%r2, 44 |
| 948 | \\ st %%r12, %%r2, 48 |
| 949 | \\ st %%r13, %%r2, 52 |
| 950 | \\ st %%r14, %%r2, 56 |
| 951 | \\ st %%r15, %%r2, 60 |
| 952 | \\ st %%r16, %%r2, 64 |
| 953 | \\ st %%r17, %%r2, 68 |
| 954 | \\ st %%r18, %%r2, 72 |
| 955 | \\ st %%r19, %%r2, 76 |
| 956 | \\ st %%r20, %%r2, 80 |
| 957 | \\ st %%r21, %%r2, 84 |
| 958 | \\ st %%r22, %%r2, 88 |
| 959 | \\ st %%r23, %%r2, 92 |
| 960 | \\ st %%r24, %%r2, 96 |
| 961 | \\ st %%r25, %%r2, 100 |
| 962 | \\ st %%r26, %%r2, 104 |
| 963 | \\ st %%r27, %%r2, 108 |
| 964 | \\ st %%r28, %%r2, 112 |
| 965 | \\ st %%r29, %%r2, 116 |
| 966 | \\ st %%r30, %%r2, 120 |
| 967 | \\ st %%r31, %%r2, 124 |
| 968 | \\ bsr.n 1f |
| 969 | \\1: |
| 970 | \\ st %%r1, %%r2, 128 |
| 971 | : |
| 972 | : [ctx] "{r2}" (&ctx), |
| 973 | : .{ .r1 = true, .memory = true }); |
| 974 | return ctx; |
| 975 | } |
| 976 | |
| 977 | pub fn getFp(ctx: *const M88k) usize { |
| 978 | return ctx.r[30]; |
| 979 | } |
| 980 | pub fn getPc(ctx: *const M88k) usize { |
| 981 | return ctx.xip; |
| 982 | } |
| 983 | |
| 984 | pub fn dwarfRegisterBytes(ctx: *M88k, register_num: u16) DwarfRegisterError![]u8 { |
| 985 | switch (register_num) { |
| 986 | 0...31 => return @ptrCast(&ctx.r[register_num]), |
| 987 | 64 => return @ptrCast(&ctx.xip), |
| 988 | |
| 989 | 32...63 => return error.UnsupportedRegister, // x0 - x31 |
| 990 | |
| 991 | else => return error.InvalidRegister, |
| 992 | } |
| 993 | } |
| 994 | }; |
| 995 | |
| 996 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| 997 | const Mips = extern struct { |
| 998 | /// The numbered general-purpose registers r0 - r31. r0 must be zero. |
| 999 | r: [32]Gpr, |
| 1000 | pc: Gpr, |
| 1001 | |
| 1002 | pub const Gpr = if (native_arch.isMIPS64()) u64 else u32; |
| 1003 | |
| 1004 | pub inline fn current() Mips { |
| 1005 | var ctx: Mips = undefined; |
| 1006 | asm volatile (if (Gpr == u64) |
| 1007 | \\ .set push |
| 1008 | \\ .set noat |
| 1009 | \\ .set noreorder |
| 1010 | \\ .set nomacro |
| 1011 | \\ sd $zero, 0($t0) |
| 1012 | \\ sd $at, 8($t0) |
| 1013 | \\ sd $v0, 16($t0) |
| 1014 | \\ sd $v1, 24($t0) |
| 1015 | \\ sd $a0, 32($t0) |
| 1016 | \\ sd $a1, 40($t0) |
| 1017 | \\ sd $a2, 48($t0) |
| 1018 | \\ sd $a3, 56($t0) |
| 1019 | \\ sd $a4, 64($t0) |
| 1020 | \\ sd $a5, 72($t0) |
| 1021 | \\ sd $a6, 80($t0) |
| 1022 | \\ sd $a7, 88($t0) |
| 1023 | \\ sd $t0, 96($t0) |
| 1024 | \\ sd $t1, 104($t0) |
| 1025 | \\ sd $t2, 112($t0) |
| 1026 | \\ sd $t3, 120($t0) |
| 1027 | \\ sd $s0, 128($t0) |
| 1028 | \\ sd $s1, 136($t0) |
| 1029 | \\ sd $s2, 144($t0) |
| 1030 | \\ sd $s3, 152($t0) |
| 1031 | \\ sd $s4, 160($t0) |
| 1032 | \\ sd $s5, 168($t0) |
| 1033 | \\ sd $s6, 176($t0) |
| 1034 | \\ sd $s7, 184($t0) |
| 1035 | \\ sd $t8, 192($t0) |
| 1036 | \\ sd $t9, 200($t0) |
| 1037 | \\ sd $k0, 208($t0) |
| 1038 | \\ sd $k1, 216($t0) |
| 1039 | \\ sd $gp, 224($t0) |
| 1040 | \\ sd $sp, 232($t0) |
| 1041 | \\ sd $fp, 240($t0) |
| 1042 | \\ sd $ra, 248($t0) |
| 1043 | \\ bal 1f |
| 1044 | \\ nop |
| 1045 | \\1: |
| 1046 | \\ sd $ra, 256($t0) |
| 1047 | \\ .set pop |
| 1048 | else |
| 1049 | \\ .set push |
| 1050 | \\ .set noat |
| 1051 | \\ .set noreorder |
| 1052 | \\ .set nomacro |
| 1053 | \\ sw $zero, 0($t4) |
| 1054 | \\ sw $at, 4($t4) |
| 1055 | \\ sw $v0, 8($t4) |
| 1056 | \\ sw $v1, 12($t4) |
| 1057 | \\ sw $a0, 16($t4) |
| 1058 | \\ sw $a1, 20($t4) |
| 1059 | \\ sw $a2, 24($t4) |
| 1060 | \\ sw $a3, 28($t4) |
| 1061 | \\ sw $t0, 32($t4) |
| 1062 | \\ sw $t1, 36($t4) |
| 1063 | \\ sw $t2, 40($t4) |
| 1064 | \\ sw $t3, 44($t4) |
| 1065 | \\ sw $t4, 48($t4) |
| 1066 | \\ sw $t5, 52($t4) |
| 1067 | \\ sw $t6, 56($t4) |
| 1068 | \\ sw $t7, 60($t4) |
| 1069 | \\ sw $s0, 64($t4) |
| 1070 | \\ sw $s1, 68($t4) |
| 1071 | \\ sw $s2, 72($t4) |
| 1072 | \\ sw $s3, 76($t4) |
| 1073 | \\ sw $s4, 80($t4) |
| 1074 | \\ sw $s5, 84($t4) |
| 1075 | \\ sw $s6, 88($t4) |
| 1076 | \\ sw $s7, 92($t4) |
| 1077 | \\ sw $t8, 96($t4) |
| 1078 | \\ sw $t9, 100($t4) |
| 1079 | \\ sw $k0, 104($t4) |
| 1080 | \\ sw $k1, 108($t4) |
| 1081 | \\ sw $gp, 112($t4) |
| 1082 | \\ sw $sp, 116($t4) |
| 1083 | \\ sw $fp, 120($t4) |
| 1084 | \\ sw $ra, 124($t4) |
| 1085 | \\ bal 1f |
| 1086 | \\ nop |
| 1087 | \\1: |
| 1088 | \\ sw $ra, 128($t4) |
| 1089 | \\ .set pop |
| 1090 | : |
| 1091 | : [ctx] "{$12}" (&ctx), |
| 1092 | : .{ .r31 = true, .memory = true }); |
| 1093 | return ctx; |
| 1094 | } |
| 1095 | |
| 1096 | pub fn getFp(ctx: *const Mips) usize { |
| 1097 | // On N32, `Gpr` is 64 bits but `usize` is 32 bits. |
| 1098 | return @intCast(ctx.r[30]); |
| 1099 | } |
| 1100 | pub fn getPc(ctx: *const Mips) usize { |
| 1101 | // On N32, `Gpr` is 64 bits but `usize` is 32 bits. |
| 1102 | return @intCast(ctx.pc); |
| 1103 | } |
| 1104 | |
| 1105 | pub fn dwarfRegisterBytes(ctx: *Mips, register_num: u16) DwarfRegisterError![]u8 { |
| 1106 | switch (register_num) { |
| 1107 | 0...31 => return @ptrCast(&ctx.r[register_num]), |
| 1108 | 66 => return @ptrCast(&ctx.pc), |
| 1109 | |
| 1110 | // Who the hell knows what numbers exist for this architecture? What's an ABI |
| 1111 | // specification anyway? We don't need that nonsense. |
| 1112 | 32...63 => return error.UnsupportedRegister, // f0 - f31, w0 - w31 |
| 1113 | 64 => return error.UnsupportedRegister, // hi0 (ac0) |
| 1114 | 65 => return error.UnsupportedRegister, // lo0 (ac0) |
| 1115 | 176 => return error.UnsupportedRegister, // hi1 (ac1) |
| 1116 | 177 => return error.UnsupportedRegister, // lo1 (ac1) |
| 1117 | 178 => return error.UnsupportedRegister, // hi2 (ac2) |
| 1118 | 179 => return error.UnsupportedRegister, // lo2 (ac2) |
| 1119 | 180 => return error.UnsupportedRegister, // hi3 (ac3) |
| 1120 | 181 => return error.UnsupportedRegister, // lo3 (ac3) |
| 1121 | |
| 1122 | else => return error.InvalidRegister, |
| 1123 | } |
| 1124 | } |
| 1125 | }; |
| 1126 | |
| 1127 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| 1128 | const Or1k = extern struct { |
| 1129 | /// The numbered general-purpose registers r0 - r31. |
| 1130 | r: [32]Gpr, |
| 1131 | pc: Gpr, |
| 1132 | |
| 1133 | pub const Gpr = u32; |
| 1134 | |
| 1135 | pub inline fn current() Or1k { |
| 1136 | var ctx: Or1k = undefined; |
| 1137 | asm volatile ( |
| 1138 | \\ l.sw 0(r15), r0 |
| 1139 | \\ l.sw 4(r15), r1 |
| 1140 | \\ l.sw 8(r15), r2 |
| 1141 | \\ l.sw 12(r15), r3 |
| 1142 | \\ l.sw 16(r15), r4 |
| 1143 | \\ l.sw 20(r15), r5 |
| 1144 | \\ l.sw 24(r15), r6 |
| 1145 | \\ l.sw 28(r15), r7 |
| 1146 | \\ l.sw 32(r15), r8 |
| 1147 | \\ l.sw 36(r15), r9 |
| 1148 | \\ l.sw 40(r15), r10 |
| 1149 | \\ l.sw 44(r15), r11 |
| 1150 | \\ l.sw 48(r15), r12 |
| 1151 | \\ l.sw 52(r15), r13 |
| 1152 | \\ l.sw 56(r15), r14 |
| 1153 | \\ l.sw 60(r15), r15 |
| 1154 | \\ l.sw 64(r15), r16 |
| 1155 | \\ l.sw 68(r15), r17 |
| 1156 | \\ l.sw 72(r15), r18 |
| 1157 | \\ l.sw 76(r15), r19 |
| 1158 | \\ l.sw 80(r15), r20 |
| 1159 | \\ l.sw 84(r15), r21 |
| 1160 | \\ l.sw 88(r15), r22 |
| 1161 | \\ l.sw 92(r15), r23 |
| 1162 | \\ l.sw 96(r15), r24 |
| 1163 | \\ l.sw 100(r15), r25 |
| 1164 | \\ l.sw 104(r15), r26 |
| 1165 | \\ l.sw 108(r15), r27 |
| 1166 | \\ l.sw 112(r15), r28 |
| 1167 | \\ l.sw 116(r15), r29 |
| 1168 | \\ l.sw 120(r15), r30 |
| 1169 | \\ l.sw 124(r15), r31 |
| 1170 | \\ l.jal 1f |
| 1171 | \\ l.nop |
| 1172 | \\1: |
| 1173 | \\ l.sw 128(r15), r9 |
| 1174 | : |
| 1175 | : [ctx] "{r15}" (&ctx), |
| 1176 | : .{ .r9 = true, .memory = true }); |
| 1177 | return ctx; |
| 1178 | } |
| 1179 | |
| 1180 | pub fn getFp(ctx: *const Or1k) usize { |
| 1181 | return ctx.r[2]; |
| 1182 | } |
| 1183 | pub fn getPc(ctx: *const Or1k) usize { |
| 1184 | return ctx.pc; |
| 1185 | } |
| 1186 | |
| 1187 | pub fn dwarfRegisterBytes(ctx: *Or1k, register_num: u16) DwarfRegisterError![]u8 { |
| 1188 | switch (register_num) { |
| 1189 | 0...31 => return @ptrCast(&ctx.r[register_num]), |
| 1190 | 35 => return @ptrCast(&ctx.pc), |
| 1191 | |
| 1192 | else => return error.InvalidRegister, |
| 1193 | } |
| 1194 | } |
| 1195 | }; |
| 1196 | |
| 1197 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| 1198 | const Powerpc = extern struct { |
| 1199 | /// The numbered general-purpose registers r0 - r31. |
| 1200 | r: [32]Gpr, |
| 1201 | pc: Gpr, |
| 1202 | lr: Gpr, |
| 1203 | |
| 1204 | pub const Gpr = if (native_arch.isPowerPC64()) u64 else u32; |
| 1205 | |
| 1206 | pub inline fn current() Powerpc { |
| 1207 | var ctx: Powerpc = undefined; |
| 1208 | asm volatile (if (Gpr == u64) |
| 1209 | \\ std 0, 0(10) |
| 1210 | \\ std 1, 8(10) |
| 1211 | \\ std 2, 16(10) |
| 1212 | \\ std 3, 24(10) |
| 1213 | \\ std 4, 32(10) |
| 1214 | \\ std 5, 40(10) |
| 1215 | \\ std 6, 48(10) |
| 1216 | \\ std 7, 56(10) |
| 1217 | \\ std 8, 64(10) |
| 1218 | \\ std 9, 72(10) |
| 1219 | \\ std 10, 80(10) |
| 1220 | \\ std 11, 88(10) |
| 1221 | \\ std 12, 96(10) |
| 1222 | \\ std 13, 104(10) |
| 1223 | \\ std 14, 112(10) |
| 1224 | \\ std 15, 120(10) |
| 1225 | \\ std 16, 128(10) |
| 1226 | \\ std 17, 136(10) |
| 1227 | \\ std 18, 144(10) |
| 1228 | \\ std 19, 152(10) |
| 1229 | \\ std 20, 160(10) |
| 1230 | \\ std 21, 168(10) |
| 1231 | \\ std 22, 176(10) |
| 1232 | \\ std 23, 184(10) |
| 1233 | \\ std 24, 192(10) |
| 1234 | \\ std 25, 200(10) |
| 1235 | \\ std 26, 208(10) |
| 1236 | \\ std 27, 216(10) |
| 1237 | \\ std 28, 224(10) |
| 1238 | \\ std 29, 232(10) |
| 1239 | \\ std 30, 240(10) |
| 1240 | \\ std 31, 248(10) |
| 1241 | \\ mflr 8 |
| 1242 | \\ std 8, 264(10) |
| 1243 | \\ bl 1f |
| 1244 | \\1: |
| 1245 | \\ mflr 8 |
| 1246 | \\ std 8, 256(10) |
| 1247 | else |
| 1248 | \\ stw 0, 0(10) |
| 1249 | \\ stw 1, 4(10) |
| 1250 | \\ stw 2, 8(10) |
| 1251 | \\ stw 3, 12(10) |
| 1252 | \\ stw 4, 16(10) |
| 1253 | \\ stw 5, 20(10) |
| 1254 | \\ stw 6, 24(10) |
| 1255 | \\ stw 7, 28(10) |
| 1256 | \\ stw 8, 32(10) |
| 1257 | \\ stw 9, 36(10) |
| 1258 | \\ stw 10, 40(10) |
| 1259 | \\ stw 11, 44(10) |
| 1260 | \\ stw 12, 48(10) |
| 1261 | \\ stw 13, 52(10) |
| 1262 | \\ stw 14, 56(10) |
| 1263 | \\ stw 15, 60(10) |
| 1264 | \\ stw 16, 64(10) |
| 1265 | \\ stw 17, 68(10) |
| 1266 | \\ stw 18, 72(10) |
| 1267 | \\ stw 19, 76(10) |
| 1268 | \\ stw 20, 80(10) |
| 1269 | \\ stw 21, 84(10) |
| 1270 | \\ stw 22, 88(10) |
| 1271 | \\ stw 23, 92(10) |
| 1272 | \\ stw 24, 96(10) |
| 1273 | \\ stw 25, 100(10) |
| 1274 | \\ stw 26, 104(10) |
| 1275 | \\ stw 27, 108(10) |
| 1276 | \\ stw 28, 112(10) |
| 1277 | \\ stw 29, 116(10) |
| 1278 | \\ stw 30, 120(10) |
| 1279 | \\ stw 31, 124(10) |
| 1280 | \\ mflr 8 |
| 1281 | \\ stw 8, 132(10) |
| 1282 | \\ bl 1f |
| 1283 | \\1: |
| 1284 | \\ mflr 8 |
| 1285 | \\ stw 8, 128(10) |
| 1286 | : |
| 1287 | : [ctx] "{r10}" (&ctx), |
| 1288 | : .{ .r8 = true, .lr = true, .memory = true }); |
| 1289 | return ctx; |
| 1290 | } |
| 1291 | |
| 1292 | pub fn getFp(ctx: *const Powerpc) usize { |
| 1293 | return ctx.r[1]; |
| 1294 | } |
| 1295 | pub fn getPc(ctx: *const Powerpc) usize { |
| 1296 | return ctx.pc; |
| 1297 | } |
| 1298 | |
| 1299 | pub fn dwarfRegisterBytes(ctx: *Powerpc, register_num: u16) DwarfRegisterError![]u8 { |
| 1300 | // References: |
| 1301 | // |
| 1302 | // * System V Application Binary Interface - PowerPC Processor Supplement §3-46 |
| 1303 | // * Power Architecture 32-bit Application Binary Interface Supplement 1.0 - Linux & Embedded §3.4 |
| 1304 | // * 64-bit ELF V2 ABI Specification - Power Architecture Revision 1.5 §2.4 |
| 1305 | // |
| 1306 | // Are we having fun yet? |
| 1307 | |
| 1308 | if (Gpr == u64) switch (register_num) { |
| 1309 | 65 => return @ptrCast(&ctx.lr), // lr |
| 1310 | |
| 1311 | 66 => return error.UnsupportedRegister, // ctr |
| 1312 | 68...75 => return error.UnsupportedRegister, // cr0 - cr7 |
| 1313 | 76 => return error.UnsupportedRegister, // xer |
| 1314 | 77...108 => return error.UnsupportedRegister, // vr0 - vr31 |
| 1315 | 109 => return error.UnsupportedRegister, // vrsave (LLVM) |
| 1316 | 110 => return error.UnsupportedRegister, // vscr |
| 1317 | 114 => return error.UnsupportedRegister, // tfhar |
| 1318 | 115 => return error.UnsupportedRegister, // tfiar |
| 1319 | 116 => return error.UnsupportedRegister, // texasr |
| 1320 | |
| 1321 | else => {}, |
| 1322 | } else switch (register_num) { |
| 1323 | 65 => return @ptrCast(&ctx.lr), // fpscr (SVR4 / EABI), or lr if you ask LLVM |
| 1324 | 108 => return @ptrCast(&ctx.lr), |
| 1325 | |
| 1326 | 64 => return error.UnsupportedRegister, // cr |
| 1327 | 66 => return error.UnsupportedRegister, // msr (SVR4 / EABI), or ctr if you ask LLVM |
| 1328 | 68...75 => return error.UnsupportedRegister, // cr0 - cr7 if you ask LLVM |
| 1329 | 76 => return error.UnsupportedRegister, // xer if you ask LLVM |
| 1330 | 99 => return error.UnsupportedRegister, // acc |
| 1331 | 100 => return error.UnsupportedRegister, // mq |
| 1332 | 101 => return error.UnsupportedRegister, // xer |
| 1333 | 102...107 => return error.UnsupportedRegister, // SPRs |
| 1334 | 109 => return error.UnsupportedRegister, // ctr |
| 1335 | 110...111 => return error.UnsupportedRegister, // SPRs |
| 1336 | 112 => return error.UnsupportedRegister, // spefscr |
| 1337 | 113...1123 => return error.UnsupportedRegister, // SPRs |
| 1338 | 1124...1155 => return error.UnsupportedRegister, // SPE v0 - v31 |
| 1339 | 1200...1231 => return error.UnsupportedRegister, // SPE upper r0 - r31 |
| 1340 | 3072...4095 => return error.UnsupportedRegister, // DCRs |
| 1341 | 4096...5120 => return error.UnsupportedRegister, // PMRs |
| 1342 | |
| 1343 | else => {}, |
| 1344 | } |
| 1345 | |
| 1346 | switch (register_num) { |
| 1347 | 0...31 => return @ptrCast(&ctx.r[register_num]), |
| 1348 | 67 => return @ptrCast(&ctx.pc), |
| 1349 | |
| 1350 | 32...63 => return error.UnsupportedRegister, // f0 - f31 |
| 1351 | |
| 1352 | else => return error.InvalidRegister, |
| 1353 | } |
| 1354 | } |
| 1355 | }; |
| 1356 | |
| 1357 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| 1358 | const Riscv = extern struct { |
| 1359 | /// The numbered general-purpose registers r0 - r31. r0 must be zero. |
| 1360 | x: [32]Gpr, |
| 1361 | pc: Gpr, |
| 1362 | |
| 1363 | pub const Gpr = if (native_arch.isRiscv64()) u64 else u32; |
| 1364 | |
| 1365 | pub inline fn current() Riscv { |
| 1366 | var ctx: Riscv = undefined; |
| 1367 | asm volatile (if (Gpr == u64) |
| 1368 | \\ sd zero, 0(t0) |
| 1369 | \\ sd ra, 8(t0) |
| 1370 | \\ sd sp, 16(t0) |
| 1371 | \\ sd gp, 24(t0) |
| 1372 | \\ sd tp, 32(t0) |
| 1373 | \\ sd t0, 40(t0) |
| 1374 | \\ sd t1, 48(t0) |
| 1375 | \\ sd t2, 56(t0) |
| 1376 | \\ sd s0, 64(t0) |
| 1377 | \\ sd s1, 72(t0) |
| 1378 | \\ sd a0, 80(t0) |
| 1379 | \\ sd a1, 88(t0) |
| 1380 | \\ sd a2, 96(t0) |
| 1381 | \\ sd a3, 104(t0) |
| 1382 | \\ sd a4, 112(t0) |
| 1383 | \\ sd a5, 120(t0) |
| 1384 | \\ sd a6, 128(t0) |
| 1385 | \\ sd a7, 136(t0) |
| 1386 | \\ sd s2, 144(t0) |
| 1387 | \\ sd s3, 152(t0) |
| 1388 | \\ sd s4, 160(t0) |
| 1389 | \\ sd s5, 168(t0) |
| 1390 | \\ sd s6, 176(t0) |
| 1391 | \\ sd s7, 184(t0) |
| 1392 | \\ sd s8, 192(t0) |
| 1393 | \\ sd s9, 200(t0) |
| 1394 | \\ sd s10, 208(t0) |
| 1395 | \\ sd s11, 216(t0) |
| 1396 | \\ sd t3, 224(t0) |
| 1397 | \\ sd t4, 232(t0) |
| 1398 | \\ sd t5, 240(t0) |
| 1399 | \\ sd t6, 248(t0) |
| 1400 | \\ jal ra, 1f |
| 1401 | \\1: |
| 1402 | \\ sd ra, 256(t0) |
| 1403 | else |
| 1404 | \\ sw zero, 0(t0) |
| 1405 | \\ sw ra, 4(t0) |
| 1406 | \\ sw sp, 8(t0) |
| 1407 | \\ sw gp, 12(t0) |
| 1408 | \\ sw tp, 16(t0) |
| 1409 | \\ sw t0, 20(t0) |
| 1410 | \\ sw t1, 24(t0) |
| 1411 | \\ sw t2, 28(t0) |
| 1412 | \\ sw s0, 32(t0) |
| 1413 | \\ sw s1, 36(t0) |
| 1414 | \\ sw a0, 40(t0) |
| 1415 | \\ sw a1, 44(t0) |
| 1416 | \\ sw a2, 48(t0) |
| 1417 | \\ sw a3, 52(t0) |
| 1418 | \\ sw a4, 56(t0) |
| 1419 | \\ sw a5, 60(t0) |
| 1420 | \\ sw a6, 64(t0) |
| 1421 | \\ sw a7, 68(t0) |
| 1422 | \\ sw s2, 72(t0) |
| 1423 | \\ sw s3, 76(t0) |
| 1424 | \\ sw s4, 80(t0) |
| 1425 | \\ sw s5, 84(t0) |
| 1426 | \\ sw s6, 88(t0) |
| 1427 | \\ sw s7, 92(t0) |
| 1428 | \\ sw s8, 96(t0) |
| 1429 | \\ sw s9, 100(t0) |
| 1430 | \\ sw s10, 104(t0) |
| 1431 | \\ sw s11, 108(t0) |
| 1432 | \\ sw t3, 112(t0) |
| 1433 | \\ sw t4, 116(t0) |
| 1434 | \\ sw t5, 120(t0) |
| 1435 | \\ sw t6, 124(t0) |
| 1436 | \\ jal ra, 1f |
| 1437 | \\1: |
| 1438 | \\ sw ra, 128(t0) |
| 1439 | : |
| 1440 | : [ctx] "{t0}" (&ctx), |
| 1441 | : .{ .x1 = true, .memory = true }); |
| 1442 | return ctx; |
| 1443 | } |
| 1444 | |
| 1445 | pub fn getFp(ctx: *const Riscv) usize { |
| 1446 | return ctx.x[8]; |
| 1447 | } |
| 1448 | pub fn getPc(ctx: *const Riscv) usize { |
| 1449 | return ctx.pc; |
| 1450 | } |
| 1451 | |
| 1452 | pub fn dwarfRegisterBytes(ctx: *Riscv, register_num: u16) DwarfRegisterError![]u8 { |
| 1453 | switch (register_num) { |
| 1454 | 0...31 => return @ptrCast(&ctx.x[register_num]), |
| 1455 | 65 => return @ptrCast(&ctx.pc), |
| 1456 | |
| 1457 | 32...63 => return error.UnsupportedRegister, // f0 - f31 |
| 1458 | 64 => return error.UnsupportedRegister, // Alternate Frame Return Column |
| 1459 | 96...127 => return error.UnsupportedRegister, // v0 - v31 |
| 1460 | 3072...4095 => return error.UnsupportedRegister, // Custom extensions |
| 1461 | 4096...8191 => return error.UnsupportedRegister, // CSRs |
| 1462 | |
| 1463 | else => return error.InvalidRegister, |
| 1464 | } |
| 1465 | } |
| 1466 | }; |
| 1467 | |
| 1468 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| 1469 | const S390x = extern struct { |
| 1470 | /// The numbered general-purpose registers r0 - r15. |
| 1471 | r: [16]Gpr, |
| 1472 | /// The program counter. |
| 1473 | psw: extern struct { |
| 1474 | mask: Gpr, |
| 1475 | addr: Gpr, |
| 1476 | }, |
| 1477 | |
| 1478 | pub const Gpr = u64; |
| 1479 | |
| 1480 | pub inline fn current() S390x { |
| 1481 | var ctx: S390x = undefined; |
| 1482 | asm volatile ( |
| 1483 | \\ stmg %%r0, %%r15, 0(%%r2) |
| 1484 | \\ epsw %%r0, %%r1 |
| 1485 | \\ stm %%r0, %%r1, 128(%%r2) |
| 1486 | \\ larl %%r0, . |
| 1487 | \\ stg %%r0, 136(%%r2) |
| 1488 | : |
| 1489 | : [ctx] "{r2}" (&ctx), |
| 1490 | : .{ .r0 = true, .r1 = true, .memory = true }); |
| 1491 | return ctx; |
| 1492 | } |
| 1493 | |
| 1494 | pub fn getFp(ctx: *const S390x) usize { |
| 1495 | return ctx.r[11]; |
| 1496 | } |
| 1497 | pub fn getPc(ctx: *const S390x) usize { |
| 1498 | return ctx.psw.addr; |
| 1499 | } |
| 1500 | |
| 1501 | pub fn dwarfRegisterBytes(ctx: *S390x, register_num: u16) DwarfRegisterError![]u8 { |
| 1502 | switch (register_num) { |
| 1503 | 0...15 => return @ptrCast(&ctx.r[register_num]), |
| 1504 | 64 => return @ptrCast(&ctx.psw.mask), |
| 1505 | 65 => return @ptrCast(&ctx.psw.addr), |
| 1506 | |
| 1507 | 16...31 => return error.UnsupportedRegister, // f0 - f15 |
| 1508 | 32...47 => return error.UnsupportedRegister, // cr0 - cr15 |
| 1509 | 48...63 => return error.UnsupportedRegister, // a0 - a15 |
| 1510 | 66...67 => return error.UnsupportedRegister, // z/OS stuff??? |
| 1511 | 68...83 => return error.UnsupportedRegister, // v16 - v31 |
| 1512 | |
| 1513 | else => return error.InvalidRegister, |
| 1514 | } |
| 1515 | } |
| 1516 | }; |
| 1517 | |
| 1518 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| 1519 | const Sparc = extern struct { |
| 1520 | g: [8]Gpr align(8), // Align to make `std` safe on 32-bit. |
| 1521 | o: [8]Gpr, |
| 1522 | l: [8]Gpr, |
| 1523 | i: [8]Gpr, |
| 1524 | pc: Gpr, |
| 1525 | |
| 1526 | pub const Gpr = if (native_arch == .sparc64) u64 else u32; |
| 1527 | |
| 1528 | pub inline fn current() Sparc { |
| 1529 | flushWindows(); |
| 1530 | |
| 1531 | var ctx: Sparc = undefined; |
| 1532 | asm volatile (if (Gpr == u64) |
| 1533 | \\ stx %%g0, [%%l0 + 0] |
| 1534 | \\ stx %%g1, [%%l0 + 8] |
| 1535 | \\ stx %%g2, [%%l0 + 16] |
| 1536 | \\ stx %%g3, [%%l0 + 24] |
| 1537 | \\ stx %%g4, [%%l0 + 32] |
| 1538 | \\ stx %%g5, [%%l0 + 40] |
| 1539 | \\ stx %%g6, [%%l0 + 48] |
| 1540 | \\ stx %%g7, [%%l0 + 56] |
| 1541 | \\ stx %%o0, [%%l0 + 64] |
| 1542 | \\ stx %%o1, [%%l0 + 72] |
| 1543 | \\ stx %%o2, [%%l0 + 80] |
| 1544 | \\ stx %%o3, [%%l0 + 88] |
| 1545 | \\ stx %%o4, [%%l0 + 96] |
| 1546 | \\ stx %%o5, [%%l0 + 104] |
| 1547 | \\ stx %%o6, [%%l0 + 112] |
| 1548 | \\ stx %%o7, [%%l0 + 120] |
| 1549 | \\ stx %%l0, [%%l0 + 128] |
| 1550 | \\ stx %%l1, [%%l0 + 136] |
| 1551 | \\ stx %%l2, [%%l0 + 144] |
| 1552 | \\ stx %%l3, [%%l0 + 152] |
| 1553 | \\ stx %%l4, [%%l0 + 160] |
| 1554 | \\ stx %%l5, [%%l0 + 168] |
| 1555 | \\ stx %%l6, [%%l0 + 176] |
| 1556 | \\ stx %%l7, [%%l0 + 184] |
| 1557 | \\ stx %%i0, [%%l0 + 192] |
| 1558 | \\ stx %%i1, [%%l0 + 200] |
| 1559 | \\ stx %%i2, [%%l0 + 208] |
| 1560 | \\ stx %%i3, [%%l0 + 216] |
| 1561 | \\ stx %%i4, [%%l0 + 224] |
| 1562 | \\ stx %%i5, [%%l0 + 232] |
| 1563 | \\ stx %%i6, [%%l0 + 240] |
| 1564 | \\ stx %%i7, [%%l0 + 248] |
| 1565 | \\ call 1f |
| 1566 | \\ nop |
| 1567 | \\1: |
| 1568 | \\ stx %%o7, [%%l0 + 256] |
| 1569 | else |
| 1570 | \\ std %%g0, [%%l0 + 0] |
| 1571 | \\ std %%g2, [%%l0 + 8] |
| 1572 | \\ std %%g4, [%%l0 + 16] |
| 1573 | \\ std %%g6, [%%l0 + 24] |
| 1574 | \\ std %%o0, [%%l0 + 32] |
| 1575 | \\ std %%o2, [%%l0 + 40] |
| 1576 | \\ std %%o4, [%%l0 + 48] |
| 1577 | \\ std %%o6, [%%l0 + 56] |
| 1578 | \\ std %%l0, [%%l0 + 64] |
| 1579 | \\ std %%l2, [%%l0 + 72] |
| 1580 | \\ std %%l4, [%%l0 + 80] |
| 1581 | \\ std %%l6, [%%l0 + 88] |
| 1582 | \\ std %%i0, [%%l0 + 96] |
| 1583 | \\ std %%i2, [%%l0 + 104] |
| 1584 | \\ std %%i4, [%%l0 + 112] |
| 1585 | \\ std %%i6, [%%l0 + 120] |
| 1586 | \\ call 1f |
| 1587 | \\ nop |
| 1588 | \\1: |
| 1589 | \\ st %%o7, [%%l0 + 128] |
| 1590 | : |
| 1591 | : [ctx] "{l0}" (&ctx), |
| 1592 | : .{ .o7 = true, .memory = true }); |
| 1593 | return ctx; |
| 1594 | } |
| 1595 | |
| 1596 | noinline fn flushWindows() void { |
| 1597 | // Flush all register windows except the current one (hence `noinline`). This ensures that |
| 1598 | // we actually see meaningful data on the stack when we walk the frame chain. |
| 1599 | if (comptime builtin.target.cpu.has(.sparc, .v9)) |
| 1600 | asm volatile ("flushw" ::: .{ .memory = true }) |
| 1601 | else |
| 1602 | asm volatile ("ta 3" ::: .{ .memory = true }); // ST_FLUSH_WINDOWS |
| 1603 | } |
| 1604 | |
| 1605 | pub fn getFp(ctx: *const Sparc) usize { |
| 1606 | return ctx.i[6]; |
| 1607 | } |
| 1608 | pub fn getPc(ctx: *const Sparc) usize { |
| 1609 | return ctx.pc; |
| 1610 | } |
| 1611 | |
| 1612 | pub fn dwarfRegisterBytes(ctx: *Sparc, register_num: u16) DwarfRegisterError![]u8 { |
| 1613 | switch (register_num) { |
| 1614 | 0...7 => return @ptrCast(&ctx.g[register_num]), |
| 1615 | 8...15 => return @ptrCast(&ctx.o[register_num - 8]), |
| 1616 | 16...23 => return @ptrCast(&ctx.l[register_num - 16]), |
| 1617 | 24...31 => return @ptrCast(&ctx.i[register_num - 24]), |
| 1618 | 65 => return @ptrCast(&ctx.pc), |
| 1619 | |
| 1620 | 32...63 => return error.UnsupportedRegister, // F0-F31 |
| 1621 | 64 => return error.UnsupportedRegister, // Y |
| 1622 | 72...87 => return error.UnsupportedRegister, // D0-D15 |
| 1623 | |
| 1624 | else => return error.InvalidRegister, |
| 1625 | } |
| 1626 | } |
| 1627 | }; |
| 1628 | |
| 1629 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| 1630 | const Ve = extern struct { |
| 1631 | s: [64]Gpr, |
| 1632 | ic: Gpr, |
| 1633 | |
| 1634 | pub const Gpr = u64; |
| 1635 | |
| 1636 | pub inline fn current() Ve { |
| 1637 | var ctx: Ve = undefined; |
| 1638 | asm volatile ( |
| 1639 | \\ st %%s0, 0(, %%s8) |
| 1640 | \\ st %%s1, 8(, %%s8) |
| 1641 | \\ st %%s2, 16(, %%s8) |
| 1642 | \\ st %%s3, 24(, %%s8) |
| 1643 | \\ st %%s4, 32(, %%s8) |
| 1644 | \\ st %%s5, 40(, %%s8) |
| 1645 | \\ st %%s6, 48(, %%s8) |
| 1646 | \\ st %%s7, 56(, %%s8) |
| 1647 | \\ st %%s8, 64(, %%s8) |
| 1648 | \\ st %%s9, 72(, %%s8) |
| 1649 | \\ st %%s10, 80(, %%s8) |
| 1650 | \\ st %%s11, 88(, %%s8) |
| 1651 | \\ st %%s12, 96(, %%s8) |
| 1652 | \\ st %%s13, 104(, %%s8) |
| 1653 | \\ st %%s14, 112(, %%s8) |
| 1654 | \\ st %%s15, 120(, %%s8) |
| 1655 | \\ st %%s16, 128(, %%s8) |
| 1656 | \\ st %%s17, 136(, %%s8) |
| 1657 | \\ st %%s18, 144(, %%s8) |
| 1658 | \\ st %%s19, 152(, %%s8) |
| 1659 | \\ st %%s20, 160(, %%s8) |
| 1660 | \\ st %%s21, 168(, %%s8) |
| 1661 | \\ st %%s22, 176(, %%s8) |
| 1662 | \\ st %%s23, 184(, %%s8) |
| 1663 | \\ st %%s24, 192(, %%s8) |
| 1664 | \\ st %%s25, 200(, %%s8) |
| 1665 | \\ st %%s26, 208(, %%s8) |
| 1666 | \\ st %%s27, 216(, %%s8) |
| 1667 | \\ st %%s28, 224(, %%s8) |
| 1668 | \\ st %%s29, 232(, %%s8) |
| 1669 | \\ st %%s30, 240(, %%s8) |
| 1670 | \\ st %%s31, 248(, %%s8) |
| 1671 | \\ st %%s32, 256(, %%s8) |
| 1672 | \\ st %%s33, 264(, %%s8) |
| 1673 | \\ st %%s34, 272(, %%s8) |
| 1674 | \\ st %%s35, 280(, %%s8) |
| 1675 | \\ st %%s36, 288(, %%s8) |
| 1676 | \\ st %%s37, 296(, %%s8) |
| 1677 | \\ st %%s38, 304(, %%s8) |
| 1678 | \\ st %%s39, 312(, %%s8) |
| 1679 | \\ st %%s40, 320(, %%s8) |
| 1680 | \\ st %%s41, 328(, %%s8) |
| 1681 | \\ st %%s42, 336(, %%s8) |
| 1682 | \\ st %%s43, 344(, %%s8) |
| 1683 | \\ st %%s44, 352(, %%s8) |
| 1684 | \\ st %%s45, 360(, %%s8) |
| 1685 | \\ st %%s46, 368(, %%s8) |
| 1686 | \\ st %%s47, 376(, %%s8) |
| 1687 | \\ st %%s48, 384(, %%s8) |
| 1688 | \\ st %%s49, 392(, %%s8) |
| 1689 | \\ st %%s50, 400(, %%s8) |
| 1690 | \\ st %%s51, 408(, %%s8) |
| 1691 | \\ st %%s52, 416(, %%s8) |
| 1692 | \\ st %%s53, 424(, %%s8) |
| 1693 | \\ st %%s54, 432(, %%s8) |
| 1694 | \\ st %%s55, 440(, %%s8) |
| 1695 | \\ st %%s56, 448(, %%s8) |
| 1696 | \\ st %%s57, 456(, %%s8) |
| 1697 | \\ st %%s58, 464(, %%s8) |
| 1698 | \\ st %%s59, 472(, %%s8) |
| 1699 | \\ st %%s60, 480(, %%s8) |
| 1700 | \\ st %%s61, 488(, %%s8) |
| 1701 | \\ st %%s62, 496(, %%s8) |
| 1702 | \\ st %%s63, 504(, %%s8) |
| 1703 | \\ sic %%s10 |
| 1704 | \\ st %%s10, 512(, %%s8) |
| 1705 | : |
| 1706 | : [ctx] "{s8}" (&ctx), |
| 1707 | : .{ .s10 = true, .memory = true }); |
| 1708 | return ctx; |
| 1709 | } |
| 1710 | |
| 1711 | pub fn getFp(ctx: *const Ve) usize { |
| 1712 | return ctx.s[9]; |
| 1713 | } |
| 1714 | pub fn getPc(ctx: *const Ve) usize { |
| 1715 | return ctx.ic; |
| 1716 | } |
| 1717 | |
| 1718 | pub fn dwarfRegisterBytes(ctx: *Ve, register_num: u16) DwarfRegisterError![]u8 { |
| 1719 | switch (register_num) { |
| 1720 | 0...63 => return @ptrCast(&ctx.s[register_num]), |
| 1721 | 144 => return @ptrCast(&ctx.ic), |
| 1722 | |
| 1723 | 64...127 => return error.UnsupportedRegister, // v0 - v63 |
| 1724 | 128...143 => return error.UnsupportedRegister, // vm0 - vm15 |
| 1725 | |
| 1726 | else => return error.InvalidRegister, |
| 1727 | } |
| 1728 | } |
| 1729 | }; |
| 1730 | |
| 1731 | const X86_16 = struct { |
| 1732 | regs: std.enums.EnumArray(GprName, Gpr), |
| 1733 | |
| 1734 | pub const GprName = enum { |
| 1735 | // zig fmt: off |
| 1736 | sp, bp, ss, |
| 1737 | ip, cs, |
| 1738 | // zig fmt: on |
| 1739 | }; |
| 1740 | pub const Gpr = u16; |
| 1741 | |
| 1742 | pub inline fn current() X86_16 { |
| 1743 | var ctx: X86_16 = undefined; |
| 1744 | asm volatile ( |
| 1745 | \\ movw %%sp, 0x00(%%di) |
| 1746 | \\ movw %%bp, 0x02(%%di) |
| 1747 | \\ movw %%ss, 0x04(%%di) |
| 1748 | \\ pushw %%cs |
| 1749 | \\ call 1f |
| 1750 | \\1: |
| 1751 | \\ popw 0x06(%%di) |
| 1752 | \\ popw 0x08(%%di) |
| 1753 | : |
| 1754 | : [gprs] "{di}" (&ctx.regs.values), |
| 1755 | : .{ .memory = true }); |
| 1756 | return ctx; |
| 1757 | } |
| 1758 | |
| 1759 | pub fn getFp(ctx: *const X86_16) usize { |
| 1760 | return ctx.regs.get(.bp); |
| 1761 | } |
| 1762 | pub fn getPc(ctx: *const X86_16) usize { |
| 1763 | return ctx.regs.get(.ip); |
| 1764 | } |
| 1765 | |
| 1766 | // NOTE: There doesn't seem to be any standard for DWARF x86-16 so we'll just reuse the ones for x86. |
| 1767 | pub fn dwarfRegisterBytes(ctx: *X86_16, register_num: u16) DwarfRegisterError![]u8 { |
| 1768 | switch (register_num) { |
| 1769 | 4 => return @ptrCast(ctx.regs.getPtr(.sp)), |
| 1770 | 5 => return @ptrCast(ctx.regs.getPtr(.bp)), |
| 1771 | 8 => return @ptrCast(ctx.regs.getPtr(.ip)), |
| 1772 | 41 => return @ptrCast(ctx.regs.getPtr(.cs)), |
| 1773 | 42 => return @ptrCast(ctx.regs.getPtr(.ss)), |
| 1774 | else => return error.InvalidRegister, |
| 1775 | } |
| 1776 | } |
| 1777 | }; |
| 1778 | |
| 1779 | const X86 = struct { |
| 1780 | gprs: std.enums.EnumArray(GprName, Gpr), |
| 1781 | |
| 1782 | /// The first 8 registers here intentionally match the order of registers in the x86 instruction |
| 1783 | /// encoding. This order is inherited by the PUSHA instruction and the DWARF register mappings, |
| 1784 | /// among other things. |
| 1785 | pub const GprName = enum { |
| 1786 | // zig fmt: off |
| 1787 | eax, ecx, edx, ebx, |
| 1788 | esp, ebp, esi, edi, |
| 1789 | eip, |
| 1790 | // zig fmt: on |
| 1791 | }; |
| 1792 | pub const Gpr = u32; |
| 1793 | |
| 1794 | pub inline fn current() X86 { |
| 1795 | var ctx: X86 = undefined; |
| 1796 | asm volatile ( |
| 1797 | \\ movl %%eax, 0x00(%%edi) |
| 1798 | \\ movl %%ecx, 0x04(%%edi) |
| 1799 | \\ movl %%edx, 0x08(%%edi) |
| 1800 | \\ movl %%ebx, 0x0c(%%edi) |
| 1801 | \\ movl %%esp, 0x10(%%edi) |
| 1802 | \\ movl %%ebp, 0x14(%%edi) |
| 1803 | \\ movl %%esi, 0x18(%%edi) |
| 1804 | \\ movl %%edi, 0x1c(%%edi) |
| 1805 | \\ call 1f |
| 1806 | \\1: |
| 1807 | \\ popl 0x20(%%edi) |
| 1808 | : |
| 1809 | : [gprs] "{edi}" (&ctx.gprs.values), |
| 1810 | : .{ .memory = true }); |
| 1811 | return ctx; |
| 1812 | } |
| 1813 | |
| 1814 | pub fn getFp(ctx: *const X86) usize { |
| 1815 | return ctx.gprs.get(.ebp); |
| 1816 | } |
| 1817 | pub fn getPc(ctx: *const X86) usize { |
| 1818 | return ctx.gprs.get(.eip); |
| 1819 | } |
| 1820 | |
| 1821 | pub fn dwarfRegisterBytes(ctx: *X86, register_num: u16) DwarfRegisterError![]u8 { |
| 1822 | // System V Application Binary Interface Intel386 Architecture Processor Supplement Version 1.1 |
| 1823 | // § 2.4.2 "DWARF Register Number Mapping" |
| 1824 | switch (register_num) { |
| 1825 | // The order of `Gpr` intentionally matches DWARF's mappings. |
| 1826 | // |
| 1827 | // x86-macos sometimes uses different mappings (ebp and esp are reversed when the unwind |
| 1828 | // information is from `__eh_frame`). This deviation is not considered here, because |
| 1829 | // x86-macos is a deprecated target which is not supported by the Zig Standard Library. |
| 1830 | 0...8 => return @ptrCast(&ctx.gprs.values[register_num]), |
| 1831 | |
| 1832 | 9 => return error.UnsupportedRegister, // eflags |
| 1833 | 11...18 => return error.UnsupportedRegister, // st0 - st7 |
| 1834 | 21...28 => return error.UnsupportedRegister, // xmm0 - xmm7 |
| 1835 | 29...36 => return error.UnsupportedRegister, // mm0 - mm7 |
| 1836 | 39 => return error.UnsupportedRegister, // mxcsr |
| 1837 | 40...45 => return error.UnsupportedRegister, // es, cs, ss, ds, fs, gs |
| 1838 | 48 => return error.UnsupportedRegister, // tr |
| 1839 | 49 => return error.UnsupportedRegister, // ldtr |
| 1840 | 93...100 => return error.UnsupportedRegister, // k0 - k7 (AVX-512) |
| 1841 | |
| 1842 | else => return error.InvalidRegister, |
| 1843 | } |
| 1844 | } |
| 1845 | }; |
| 1846 | |
| 1847 | const X86_64 = struct { |
| 1848 | gprs: std.enums.EnumArray(GprName, Gpr), |
| 1849 | |
| 1850 | /// The order here intentionally matches the order of the DWARF register mappings. It's unclear |
| 1851 | /// where those mappings actually originated from---the ordering of the first 4 registers seems |
| 1852 | /// quite unusual---but it is currently convenient for us to match DWARF. |
| 1853 | pub const GprName = enum { |
| 1854 | // zig fmt: off |
| 1855 | rax, rdx, rcx, rbx, |
| 1856 | rsi, rdi, rbp, rsp, |
| 1857 | r8, r9, r10, r11, |
| 1858 | r12, r13, r14, r15, |
| 1859 | rip, |
| 1860 | // zig fmt: on |
| 1861 | }; |
| 1862 | pub const Gpr = u64; |
| 1863 | |
| 1864 | pub inline fn current() X86_64 { |
| 1865 | var ctx: X86_64 = undefined; |
| 1866 | asm volatile ( |
| 1867 | \\ movq %%rax, 0x00(%%rdi) |
| 1868 | \\ movq %%rdx, 0x08(%%rdi) |
| 1869 | \\ movq %%rcx, 0x10(%%rdi) |
| 1870 | \\ movq %%rbx, 0x18(%%rdi) |
| 1871 | \\ movq %%rsi, 0x20(%%rdi) |
| 1872 | \\ movq %%rdi, 0x28(%%rdi) |
| 1873 | \\ movq %%rbp, 0x30(%%rdi) |
| 1874 | \\ movq %%rsp, 0x38(%%rdi) |
| 1875 | \\ movq %%r8, 0x40(%%rdi) |
| 1876 | \\ movq %%r9, 0x48(%%rdi) |
| 1877 | \\ movq %%r10, 0x50(%%rdi) |
| 1878 | \\ movq %%r11, 0x58(%%rdi) |
| 1879 | \\ movq %%r12, 0x60(%%rdi) |
| 1880 | \\ movq %%r13, 0x68(%%rdi) |
| 1881 | \\ movq %%r14, 0x70(%%rdi) |
| 1882 | \\ movq %%r15, 0x78(%%rdi) |
| 1883 | \\ leaq (%%rip), %%rax |
| 1884 | \\ movq %%rax, 0x80(%%rdi) |
| 1885 | : |
| 1886 | : [gprs] "{rdi}" (&ctx.gprs.values), |
| 1887 | : .{ .rax = true, .memory = true }); |
| 1888 | return ctx; |
| 1889 | } |
| 1890 | |
| 1891 | pub fn getFp(ctx: *const X86_64) usize { |
| 1892 | // On x32, registers are 64 bits but `usize` is 32 bits. |
| 1893 | return @intCast(ctx.gprs.get(.rbp)); |
| 1894 | } |
| 1895 | pub fn getPc(ctx: *const X86_64) usize { |
| 1896 | // On x32, registers are 64 bits but `usize` is 32 bits. |
| 1897 | return @intCast(ctx.gprs.get(.rip)); |
| 1898 | } |
| 1899 | |
| 1900 | pub fn dwarfRegisterBytes(ctx: *X86_64, register_num: u16) DwarfRegisterError![]u8 { |
| 1901 | // System V Application Binary Interface AMD64 Architecture Processor Supplement |
| 1902 | // § 3.6.2 "DWARF Register Number Mapping" |
| 1903 | switch (register_num) { |
| 1904 | // The order of `Gpr` intentionally matches DWARF's mappings. |
| 1905 | 0...16 => return @ptrCast(&ctx.gprs.values[register_num]), |
| 1906 | |
| 1907 | 17...32 => return error.UnsupportedRegister, // xmm0 - xmm15 |
| 1908 | 33...40 => return error.UnsupportedRegister, // st0 - st7 |
| 1909 | 41...48 => return error.UnsupportedRegister, // mm0 - mm7 |
| 1910 | 49 => return error.UnsupportedRegister, // rflags |
| 1911 | 50...55 => return error.UnsupportedRegister, // es, cs, ss, ds, fs, gs |
| 1912 | 58...59 => return error.UnsupportedRegister, // fs.base, gs.base |
| 1913 | 62 => return error.UnsupportedRegister, // tr |
| 1914 | 63 => return error.UnsupportedRegister, // ldtr |
| 1915 | 64 => return error.UnsupportedRegister, // mxcsr |
| 1916 | 65 => return error.UnsupportedRegister, // fcw |
| 1917 | 66 => return error.UnsupportedRegister, // fsw |
| 1918 | 67...82 => return error.UnsupportedRegister, // xmm16 - xmm31 (AVX-512) |
| 1919 | 118...125 => return error.UnsupportedRegister, // k0 - k7 (AVX-512) |
| 1920 | 130...145 => return error.UnsupportedRegister, // r16 - r31 (APX) |
| 1921 | |
| 1922 | else => return error.InvalidRegister, |
| 1923 | } |
| 1924 | } |
| 1925 | }; |
| 1926 | |
| 1927 | /// The native operating system's `ucontext_t` as seen in the third argument to signal handlers. |
| 1928 | /// |
| 1929 | /// These are dramatically simplified since we only need general-purpose registers and don't care |
| 1930 | /// about all the complicated extension state (floating point, vector, etc). This means that these |
| 1931 | /// structures are almost all shorter than the real ones, which is safe because we only access them |
| 1932 | /// through a pointer. |
| 1933 | /// |
| 1934 | /// Some effort is made to have structures for the same architecture use the same access pattern, |
| 1935 | /// e.g. `uc.mcontext.x` for `aarch64-linux` and `aarch64-freebsd` even though that's not quite how |
| 1936 | /// they're declared and spelled in the C headers for both targets. Similarly, registers are typed |
| 1937 | /// as unsigned everywhere even if that's not how they're declared in the C headers. |
| 1938 | const signal_ucontext_t = switch (native_os) { |
| 1939 | .linux => switch (native_arch) { |
| 1940 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/alpha/include/asm/ucontext.h |
| 1941 | .alpha => extern struct { |
| 1942 | _flags: u64, |
| 1943 | _link: ?*signal_ucontext_t, |
| 1944 | _osf_sigmask: u64, |
| 1945 | _stack: std.os.linux.stack_t, |
| 1946 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/alpha/include/uapi/asm/sigcontext.h |
| 1947 | mcontext: extern struct { |
| 1948 | _onstack: i64, |
| 1949 | _mask: i64, |
| 1950 | pc: u64, |
| 1951 | _ps: i64, |
| 1952 | r: [32]u64, |
| 1953 | }, |
| 1954 | }, |
| 1955 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/arm64/include/uapi/asm/ucontext.h |
| 1956 | .aarch64, |
| 1957 | .aarch64_be, |
| 1958 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/loongarch/include/uapi/asm/ucontext.h |
| 1959 | .loongarch32, |
| 1960 | .loongarch64, |
| 1961 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/powerpc/include/uapi/asm/ucontext.h |
| 1962 | .powerpc64, |
| 1963 | .powerpc64le, |
| 1964 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/riscv/include/uapi/asm/ucontext.h |
| 1965 | .riscv32, |
| 1966 | .riscv64, |
| 1967 | => extern struct { |
| 1968 | _flags: usize, |
| 1969 | _link: ?*signal_ucontext_t, |
| 1970 | _stack: std.os.linux.stack_t, |
| 1971 | _sigmask: std.os.linux.sigset_t, |
| 1972 | _unused: [120]u8, |
| 1973 | mcontext: switch (native_arch) { |
| 1974 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/arm64/include/uapi/asm/sigcontext.h |
| 1975 | .aarch64, .aarch64_be => extern struct { |
| 1976 | _fault_address: u64 align(16), |
| 1977 | x: [30]u64, |
| 1978 | lr: u64, |
| 1979 | sp: u64, |
| 1980 | pc: u64, |
| 1981 | }, |
| 1982 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/loongarch/include/uapi/asm/sigcontext.h |
| 1983 | .loongarch32, .loongarch64 => extern struct { |
| 1984 | pc: u64 align(16), |
| 1985 | r: [32]u64, |
| 1986 | }, |
| 1987 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/powerpc/include/uapi/asm/sigcontext.h |
| 1988 | .powerpc64, .powerpc64le => extern struct { |
| 1989 | _unused: [4]u64, |
| 1990 | _signal: i32, |
| 1991 | _pad: i32, |
| 1992 | _handler: u64, |
| 1993 | _oldmask: u64, |
| 1994 | _regs: ?*anyopaque, |
| 1995 | r: [32]u64, |
| 1996 | pc: u64, |
| 1997 | _msr: u64, |
| 1998 | _orig_r3: u64, |
| 1999 | _ctr: u64, |
| 2000 | lr: u64, |
| 2001 | }, |
| 2002 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/riscv/include/uapi/asm/sigcontext.h |
| 2003 | .riscv32, .riscv64 => extern struct { |
| 2004 | pc: usize align(16), |
| 2005 | ra_sp_gp_tp: [4]usize, |
| 2006 | t0_2: [3]usize, |
| 2007 | s0_1: [2]usize, |
| 2008 | a: [8]usize, |
| 2009 | s2_11: [10]usize, |
| 2010 | t3_6: [4]usize, |
| 2011 | }, |
| 2012 | else => unreachable, |
| 2013 | }, |
| 2014 | }, |
| 2015 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/include/uapi/asm-generic/ucontext.h |
| 2016 | .arc, |
| 2017 | .arceb, |
| 2018 | .arm, |
| 2019 | .armeb, |
| 2020 | .thumb, |
| 2021 | .thumbeb, |
| 2022 | .csky, |
| 2023 | .hexagon, |
| 2024 | .hppa, |
| 2025 | .hppa64, |
| 2026 | .m68k, |
| 2027 | .mips, |
| 2028 | .mipsel, |
| 2029 | .mips64, |
| 2030 | .mips64el, |
| 2031 | .or1k, |
| 2032 | .s390x, |
| 2033 | .sh, |
| 2034 | .sheb, |
| 2035 | .x86, |
| 2036 | .x86_64, |
| 2037 | .xtensa, |
| 2038 | .xtensaeb, |
| 2039 | => extern struct { |
| 2040 | _flags: usize, |
| 2041 | _link: ?*signal_ucontext_t, |
| 2042 | _stack: std.os.linux.stack_t, |
| 2043 | mcontext: switch (native_arch) { |
| 2044 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/arc/include/uapi/asm/sigcontext.h |
| 2045 | .arc, .arceb => extern struct { |
| 2046 | _pad1: u32, |
| 2047 | _bta: u32, |
| 2048 | _lp: extern struct { |
| 2049 | _start: u32, |
| 2050 | _end: u32, |
| 2051 | _count: u32, |
| 2052 | }, |
| 2053 | _status32: u32, |
| 2054 | pcl: u32, |
| 2055 | r31: u32, |
| 2056 | r27_26: [2]u32, |
| 2057 | r12_0: [13]u32, |
| 2058 | r28: u32, |
| 2059 | _pad2: u32, |
| 2060 | r25_13: [13]u32, |
| 2061 | _efa: u32, |
| 2062 | _stop_pc: u32, |
| 2063 | r30: u32, |
| 2064 | }, |
| 2065 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/arm/include/uapi/asm/sigcontext.h |
| 2066 | .arm, .armeb, .thumb, .thumbeb => extern struct { |
| 2067 | _trap_no: u32, |
| 2068 | _error_code: u32, |
| 2069 | _oldmask: u32, |
| 2070 | r: [15]u32, |
| 2071 | pc: u32, |
| 2072 | }, |
| 2073 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/csky/include/uapi/asm/sigcontext.h |
| 2074 | .csky => extern struct { |
| 2075 | r31: u32, |
| 2076 | r15: u32, |
| 2077 | pc: u32, |
| 2078 | _sr: u32, |
| 2079 | r14: u32, |
| 2080 | _orig_a0: u32, |
| 2081 | r0_13: [14]u32, |
| 2082 | r16_30: [15]u32, |
| 2083 | }, |
| 2084 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/hexagon/include/uapi/asm/sigcontext.h |
| 2085 | .hexagon => extern struct { |
| 2086 | r: [32]u32 align(8), |
| 2087 | _salc: [2]extern struct { |
| 2088 | _sa: u32, |
| 2089 | _lc: u32, |
| 2090 | }, |
| 2091 | _m: [2]u32, |
| 2092 | _usr: u32, |
| 2093 | _p: u32, |
| 2094 | _gp: u32, |
| 2095 | _ugp: u32, |
| 2096 | pc: u32, |
| 2097 | }, |
| 2098 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/parisc/include/uapi/asm/sigcontext.h |
| 2099 | .hppa, .hppa64 => extern struct { |
| 2100 | _flags: usize, |
| 2101 | _psw: usize, |
| 2102 | r1_19: [19]usize, |
| 2103 | r20: usize, |
| 2104 | r21: usize, |
| 2105 | r22: usize, |
| 2106 | r23_29: [7]usize, |
| 2107 | r30: usize, |
| 2108 | r31: usize, |
| 2109 | _fr: [32]f64, |
| 2110 | _iasq: [2]usize, |
| 2111 | iaoq: [2]usize, |
| 2112 | }, |
| 2113 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/m68k/include/asm/ucontext.h |
| 2114 | .m68k => extern struct { |
| 2115 | _version: i32, |
| 2116 | d: [8]u32, |
| 2117 | a: [8]u32, |
| 2118 | pc: u32, |
| 2119 | }, |
| 2120 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/microblaze/include/uapi/asm/sigcontext.h |
| 2121 | .microblaze, .microblazeel => extern struct { |
| 2122 | r: [32]u32, |
| 2123 | pc: u32, |
| 2124 | }, |
| 2125 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/mips/include/uapi/asm/sigcontext.h |
| 2126 | .mips, .mipsel => extern struct { |
| 2127 | _regmask: u32, |
| 2128 | _status: u32, |
| 2129 | // ??? A spectacularly failed attempt to be future-proof? |
| 2130 | pc: u64, |
| 2131 | r: [32]u64, |
| 2132 | }, |
| 2133 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/mips/include/uapi/asm/sigcontext.h |
| 2134 | .mips64, .mips64el => extern struct { |
| 2135 | r: [32]u64, |
| 2136 | _fpregs: [32]u64, |
| 2137 | _hi: [4]u64, |
| 2138 | _lo: [4]u64, |
| 2139 | pc: u64, |
| 2140 | }, |
| 2141 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/openrisc/include/uapi/asm/sigcontext.h |
| 2142 | .or1k => extern struct { |
| 2143 | r: [32]u32, |
| 2144 | pc: u32, |
| 2145 | }, |
| 2146 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/s390/include/uapi/asm/sigcontext.h |
| 2147 | .s390x => extern struct { |
| 2148 | psw: extern struct { |
| 2149 | mask: u64, |
| 2150 | addr: u64, |
| 2151 | }, |
| 2152 | r: [16]u64, |
| 2153 | }, |
| 2154 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/sh/include/uapi/asm/sigcontext.h |
| 2155 | .sh, .sheb => extern struct { |
| 2156 | _oldmask: u32, |
| 2157 | r: [16]u32, |
| 2158 | pc: u32, |
| 2159 | pr: u32, |
| 2160 | }, |
| 2161 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/x86/include/uapi/asm/sigcontext.h |
| 2162 | .x86 => extern struct { |
| 2163 | _gs: u32, |
| 2164 | _fs: u32, |
| 2165 | _es: u32, |
| 2166 | _ds: u32, |
| 2167 | edi: u32, |
| 2168 | esi: u32, |
| 2169 | ebp: u32, |
| 2170 | esp: u32, |
| 2171 | ebx: u32, |
| 2172 | edx: u32, |
| 2173 | ecx: u32, |
| 2174 | eax: u32, |
| 2175 | _trapno: u32, |
| 2176 | _err: u32, |
| 2177 | eip: u32, |
| 2178 | }, |
| 2179 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/x86/include/uapi/asm/sigcontext.h |
| 2180 | .x86_64 => extern struct { |
| 2181 | r8: u64, |
| 2182 | r9: u64, |
| 2183 | r10: u64, |
| 2184 | r11: u64, |
| 2185 | r12: u64, |
| 2186 | r13: u64, |
| 2187 | r14: u64, |
| 2188 | r15: u64, |
| 2189 | rdi: u64, |
| 2190 | rsi: u64, |
| 2191 | rbp: u64, |
| 2192 | rbx: u64, |
| 2193 | rdx: u64, |
| 2194 | rax: u64, |
| 2195 | rcx: u64, |
| 2196 | rsp: u64, |
| 2197 | rip: u64, |
| 2198 | }, |
| 2199 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/xtensa/include/uapi/asm/sigcontext.h |
| 2200 | .xtensa, .xtensaeb => extern struct { |
| 2201 | pc: u32, |
| 2202 | _ps: u32, |
| 2203 | _l: extern struct { |
| 2204 | _beg: u32, |
| 2205 | _end: u32, |
| 2206 | _count: u32, |
| 2207 | }, |
| 2208 | _sar: u32, |
| 2209 | _acc: extern struct { |
| 2210 | _lo: u32, |
| 2211 | _hi: u32, |
| 2212 | }, |
| 2213 | a: [16]u32, |
| 2214 | }, |
| 2215 | else => unreachable, |
| 2216 | }, |
| 2217 | }, |
| 2218 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/powerpc/include/uapi/asm/ucontext.h |
| 2219 | .powerpc, .powerpcle => extern struct { |
| 2220 | _flags: u32, |
| 2221 | _link: ?*signal_ucontext_t, |
| 2222 | _stack: std.os.linux.stack_t, |
| 2223 | _pad1: [7]i32, |
| 2224 | _regs: ?*anyopaque, |
| 2225 | _sigmask: std.os.linux.sigset_t, |
| 2226 | _unused: [120]u8, |
| 2227 | _pad2: [3]i32, |
| 2228 | mcontext: extern struct { |
| 2229 | r: [32]u32 align(16), |
| 2230 | pc: u32, |
| 2231 | _msr: u32, |
| 2232 | _orig_r3: u32, |
| 2233 | _ctr: u32, |
| 2234 | lr: u32, |
| 2235 | }, |
| 2236 | }, |
| 2237 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/sparc/kernel/signal_32.c#L48-L49 |
| 2238 | .sparc => extern struct { |
| 2239 | // Not actually a `ucontext_t` at all because, uh, reasons? |
| 2240 | |
| 2241 | _info: std.os.linux.siginfo_t, |
| 2242 | mcontext: extern struct { |
| 2243 | _psr: u32, |
| 2244 | pc: u32, |
| 2245 | _npc: u32, |
| 2246 | _y: u32, |
| 2247 | g: [8]u32, |
| 2248 | o: [8]u32, |
| 2249 | }, |
| 2250 | }, |
| 2251 | // https://github.com/torvalds/linux/blob/cd5a0afbdf8033dc83786315d63f8b325bdba2fd/arch/sparc/kernel/signal_64.c#L247-L248 |
| 2252 | .sparc64 => extern struct { |
| 2253 | // Ditto... |
| 2254 | |
| 2255 | _info: std.os.linux.siginfo_t, |
| 2256 | mcontext: extern struct { |
| 2257 | g: [8]u64, |
| 2258 | o: [8]u64, |
| 2259 | _tstate: u64, |
| 2260 | pc: u64, |
| 2261 | }, |
| 2262 | }, |
| 2263 | else => unreachable, |
| 2264 | }, |
| 2265 | // https://github.com/freebsd/freebsd-src/blob/55c28005f544282b984ae0e15dacd0c108d8ab12/sys/sys/_ucontext.h |
| 2266 | .freebsd => extern struct { |
| 2267 | _sigmask: std.c.sigset_t, |
| 2268 | mcontext: switch (native_arch) { |
| 2269 | // https://github.com/freebsd/freebsd-src/blob/55c28005f544282b984ae0e15dacd0c108d8ab12/sys/arm64/include/ucontext.h |
| 2270 | .aarch64 => extern struct { |
| 2271 | x: [30]u64 align(16), |
| 2272 | lr: u64, |
| 2273 | sp: u64, |
| 2274 | pc: u64, |
| 2275 | }, |
| 2276 | // https://github.com/freebsd/freebsd-src/blob/55c28005f544282b984ae0e15dacd0c108d8ab12/sys/arm/include/ucontext.h |
| 2277 | .arm => extern struct { |
| 2278 | r: [15]u32, |
| 2279 | pc: u32, |
| 2280 | }, |
| 2281 | // https://github.com/freebsd/freebsd-src/blob/55c28005f544282b984ae0e15dacd0c108d8ab12/sys/powerpc/include/ucontext.h |
| 2282 | .powerpc64, .powerpc64le => extern struct { |
| 2283 | _vers: i32 align(16), |
| 2284 | _flags: i32, |
| 2285 | _onstack: i32, |
| 2286 | _len: i32, |
| 2287 | _avec: [32 * 2]u64, |
| 2288 | _av: [2]u32, |
| 2289 | r: [32]u64, |
| 2290 | lr: u64, |
| 2291 | _cr: u64, |
| 2292 | _xer: u64, |
| 2293 | _ctr: u64, |
| 2294 | pc: u64, |
| 2295 | }, |
| 2296 | // https://github.com/freebsd/freebsd-src/blob/55c28005f544282b984ae0e15dacd0c108d8ab12/sys/riscv/include/ucontext.h |
| 2297 | .riscv64 => extern struct { |
| 2298 | ra_sp_gp_tp: [4]u64, |
| 2299 | t0_2: [3]u64, |
| 2300 | t3_6: [4]u64, |
| 2301 | s0_1: [2]u64, |
| 2302 | s2_11: [10]u64, |
| 2303 | a: [8]u64, |
| 2304 | pc: u64, |
| 2305 | }, |
| 2306 | // https://github.com/freebsd/freebsd-src/blob/55c28005f544282b984ae0e15dacd0c108d8ab12/sys/x86/include/ucontext.h |
| 2307 | .x86 => extern struct { |
| 2308 | _onstack: i32 align(16), |
| 2309 | _gs: i32, |
| 2310 | _fs: i32, |
| 2311 | _es: i32, |
| 2312 | _ds: i32, |
| 2313 | edi: u32, |
| 2314 | esi: u32, |
| 2315 | ebp: u32, |
| 2316 | _isp: i32, |
| 2317 | ebx: u32, |
| 2318 | edx: u32, |
| 2319 | ecx: u32, |
| 2320 | eax: u32, |
| 2321 | _trapno: i32, |
| 2322 | _err: i32, |
| 2323 | eip: u32, |
| 2324 | _cs: i32, |
| 2325 | _eflags: i32, |
| 2326 | esp: u32, |
| 2327 | }, |
| 2328 | // https://github.com/freebsd/freebsd-src/blob/55c28005f544282b984ae0e15dacd0c108d8ab12/sys/x86/include/ucontext.h |
| 2329 | .x86_64 => extern struct { |
| 2330 | _onstack: i64 align(16), |
| 2331 | rdi: u64, |
| 2332 | rsi: u64, |
| 2333 | rdx: u64, |
| 2334 | rcx: u64, |
| 2335 | r8: u64, |
| 2336 | r9: u64, |
| 2337 | rax: u64, |
| 2338 | rbx: u64, |
| 2339 | rbp: u64, |
| 2340 | r10: u64, |
| 2341 | r11: u64, |
| 2342 | r12: u64, |
| 2343 | r13: u64, |
| 2344 | r14: u64, |
| 2345 | r15: u64, |
| 2346 | _trapno: i32, |
| 2347 | _fs: i16, |
| 2348 | _gs: i16, |
| 2349 | _addr: i64, |
| 2350 | _flags: i32, |
| 2351 | _es: i16, |
| 2352 | _ds: i16, |
| 2353 | _err: i64, |
| 2354 | rip: u64, |
| 2355 | _cs: i64, |
| 2356 | _rflags: i64, |
| 2357 | rsp: u64, |
| 2358 | }, |
| 2359 | else => unreachable, |
| 2360 | }, |
| 2361 | }, |
| 2362 | // https://github.com/ziglang/zig/blob/60be67d3c0ba6ae15fa7115596734ab1e74fbcd3/lib/libc/include/any-macos-any/sys/_types/_ucontext.h |
| 2363 | .driverkit, .ios, .maccatalyst, .macos, .tvos, .watchos, .visionos => extern struct { |
| 2364 | _onstack: i32, |
| 2365 | _sigmask: std.c.sigset_t, |
| 2366 | _stack: std.c.stack_t, |
| 2367 | _link: ?*signal_ucontext_t, |
| 2368 | _mcsize: u64, |
| 2369 | mcontext: *switch (native_arch) { |
| 2370 | // https://github.com/ziglang/zig/blob/60be67d3c0ba6ae15fa7115596734ab1e74fbcd3/lib/libc/include/any-macos-any/arm/_mcontext.h |
| 2371 | // https://github.com/ziglang/zig/blob/60be67d3c0ba6ae15fa7115596734ab1e74fbcd3/lib/libc/include/any-macos-any/mach/arm/_structs.h |
| 2372 | .aarch64 => extern struct { |
| 2373 | _far: u64 align(16), |
| 2374 | _esr: u64, |
| 2375 | x: [30]u64, |
| 2376 | lr: u64, |
| 2377 | sp: u64, |
| 2378 | pc: u64, |
| 2379 | }, |
| 2380 | // https://github.com/ziglang/zig/blob/60be67d3c0ba6ae15fa7115596734ab1e74fbcd3/lib/libc/include/any-macos-any/i386/_mcontext.h |
| 2381 | // https://github.com/ziglang/zig/blob/60be67d3c0ba6ae15fa7115596734ab1e74fbcd3/lib/libc/include/any-macos-any/mach/i386/_structs.h |
| 2382 | .x86_64 => extern struct { |
| 2383 | _trapno: u16, |
| 2384 | _cpu: u16, |
| 2385 | _err: u32, |
| 2386 | _faultvaddr: u64, |
| 2387 | rax: u64, |
| 2388 | rbx: u64, |
| 2389 | rcx: u64, |
| 2390 | rdx: u64, |
| 2391 | rdi: u64, |
| 2392 | rsi: u64, |
| 2393 | rbp: u64, |
| 2394 | rsp: u64, |
| 2395 | r8: u64, |
| 2396 | r9: u64, |
| 2397 | r10: u64, |
| 2398 | r11: u64, |
| 2399 | r12: u64, |
| 2400 | r13: u64, |
| 2401 | r14: u64, |
| 2402 | r15: u64, |
| 2403 | rip: u64, |
| 2404 | }, |
| 2405 | else => unreachable, |
| 2406 | }, |
| 2407 | }, |
| 2408 | // https://github.com/illumos/illumos-gate/blob/d4ce137bba3bd16823db6374d9e9a643264ce245/usr/src/uts/intel/sys/ucontext.h |
| 2409 | .illumos => extern struct { |
| 2410 | _flags: usize, |
| 2411 | _link: ?*signal_ucontext_t, |
| 2412 | _sigmask: std.c.sigset_t, |
| 2413 | _stack: std.c.stack_t, |
| 2414 | mcontext: switch (native_arch) { |
| 2415 | // https://github.com/illumos/illumos-gate/blob/d4ce137bba3bd16823db6374d9e9a643264ce245/usr/src/uts/intel/sys/mcontext.h |
| 2416 | .x86 => extern struct { |
| 2417 | _gs: u32, |
| 2418 | _fs: u32, |
| 2419 | _es: u32, |
| 2420 | _ds: u32, |
| 2421 | edi: u32, |
| 2422 | esi: u32, |
| 2423 | ebp: u32, |
| 2424 | esp: u32, |
| 2425 | ebx: u32, |
| 2426 | edx: u32, |
| 2427 | ecx: u32, |
| 2428 | eax: u32, |
| 2429 | _trapno: i32, |
| 2430 | _err: i32, |
| 2431 | eip: u32, |
| 2432 | }, |
| 2433 | // https://github.com/illumos/illumos-gate/blob/d4ce137bba3bd16823db6374d9e9a643264ce245/usr/src/uts/intel/sys/mcontext.h |
| 2434 | .x86_64 => extern struct { |
| 2435 | r15: u64 align(16), |
| 2436 | r14: u64, |
| 2437 | r13: u64, |
| 2438 | r12: u64, |
| 2439 | r11: u64, |
| 2440 | r10: u64, |
| 2441 | r9: u64, |
| 2442 | r8: u64, |
| 2443 | rdi: u64, |
| 2444 | rsi: u64, |
| 2445 | rbp: u64, |
| 2446 | rbx: u64, |
| 2447 | rdx: u64, |
| 2448 | rcx: u64, |
| 2449 | rax: u64, |
| 2450 | _trapno: i64, |
| 2451 | _err: i64, |
| 2452 | rip: u64, |
| 2453 | _cs: i64, |
| 2454 | _rflags: i64, |
| 2455 | rsp: u64, |
| 2456 | }, |
| 2457 | else => unreachable, |
| 2458 | }, |
| 2459 | }, |
| 2460 | .openbsd => switch (native_arch) { |
| 2461 | // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/arm64/include/signal.h |
| 2462 | .aarch64 => extern struct { |
| 2463 | _unused: i32, |
| 2464 | _mask: i32, |
| 2465 | mcontext: extern struct { |
| 2466 | sp: u64, |
| 2467 | lr: u64, |
| 2468 | pc: u64, |
| 2469 | _spsr: u64, |
| 2470 | x: [30]u64, |
| 2471 | }, |
| 2472 | }, |
| 2473 | // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/alpha/include/signal.h |
| 2474 | .alpha => extern struct { |
| 2475 | _cookie: i64, |
| 2476 | _mask: i64, |
| 2477 | mcontext: extern struct { |
| 2478 | pc: u64, |
| 2479 | _ps: i64, |
| 2480 | r: [32]u64, |
| 2481 | }, |
| 2482 | }, |
| 2483 | // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/arm/include/signal.h |
| 2484 | .arm => extern struct { |
| 2485 | _cookie: i32, |
| 2486 | _mask: i32, |
| 2487 | mcontext: extern struct { |
| 2488 | _spsr: u32 align(8), |
| 2489 | r: [15]u32, |
| 2490 | _svc_lr: u32, |
| 2491 | pc: u32, |
| 2492 | }, |
| 2493 | }, |
| 2494 | // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/hppa/include/signal.h |
| 2495 | .hppa => extern struct { |
| 2496 | _unused: u32, |
| 2497 | _mask: i32, |
| 2498 | _fp: u32, |
| 2499 | iaoq: [2]u32, |
| 2500 | _resv: [2]u32, |
| 2501 | r22: u32, |
| 2502 | r21: u32, |
| 2503 | r30: u32, |
| 2504 | r20: u32, |
| 2505 | _sar: u32, |
| 2506 | r1_19: [19]u32, |
| 2507 | r23_29: [7]u32, |
| 2508 | r31: u32, |
| 2509 | }, |
| 2510 | // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/m88k/include/signal.h |
| 2511 | .m88k => extern struct { |
| 2512 | _cookie: i32, |
| 2513 | _mask: i32, |
| 2514 | mcontext: extern struct { |
| 2515 | r: [32]u32, |
| 2516 | _epsr: u32, |
| 2517 | _fpsr: u32, |
| 2518 | _fpcr: u32, |
| 2519 | xip: u32, |
| 2520 | }, |
| 2521 | }, |
| 2522 | // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/mips64/include/signal.h |
| 2523 | .mips64, .mips64el => extern struct { |
| 2524 | _cookie: i64, |
| 2525 | _mask: i64, |
| 2526 | mcontext: extern struct { |
| 2527 | pc: u64, |
| 2528 | r: [32]u64, |
| 2529 | }, |
| 2530 | }, |
| 2531 | // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/powerpc/include/signal.h |
| 2532 | // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/powerpc64/include/signal.h |
| 2533 | .powerpc, .powerpc64 => extern struct { |
| 2534 | _cookie: isize, |
| 2535 | _mask: i32, |
| 2536 | mcontext: extern struct { |
| 2537 | r: [32]usize, |
| 2538 | lr: usize, |
| 2539 | _cr: usize, |
| 2540 | _xer: usize, |
| 2541 | _ctr: usize, |
| 2542 | pc: usize, |
| 2543 | }, |
| 2544 | }, |
| 2545 | // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/riscv64/include/signal.h |
| 2546 | .riscv64 => extern struct { |
| 2547 | _unused: i32, |
| 2548 | _mask: i32, |
| 2549 | mcontext: extern struct { |
| 2550 | ra_sp_gp_tp: [4]u64, |
| 2551 | t0_2: [3]u64, |
| 2552 | t3_6: [4]u64, |
| 2553 | s0_1: [2]u64, |
| 2554 | s2_11: [10]u64, |
| 2555 | a: [8]u64, |
| 2556 | pc: u64, |
| 2557 | }, |
| 2558 | }, |
| 2559 | // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/sparc64/include/signal.h |
| 2560 | .sparc64 => @compileError("sparc64-openbsd ucontext_t missing"), |
| 2561 | // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/sh/include/signal.h |
| 2562 | .sh => extern struct { |
| 2563 | pc: u32, |
| 2564 | _sr: i32, |
| 2565 | _gbr: i32, |
| 2566 | _macl: i32, |
| 2567 | _mach: i32, |
| 2568 | pr: u32, |
| 2569 | r13_0: [14]u32, |
| 2570 | r15: u32, |
| 2571 | r14: u32, |
| 2572 | }, |
| 2573 | // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/i386/include/signal.h |
| 2574 | .x86 => extern struct { |
| 2575 | mcontext: extern struct { |
| 2576 | _gs: i32, |
| 2577 | _fs: i32, |
| 2578 | _es: i32, |
| 2579 | _ds: i32, |
| 2580 | edi: u32, |
| 2581 | esi: u32, |
| 2582 | ebp: u32, |
| 2583 | ebx: u32, |
| 2584 | edx: u32, |
| 2585 | ecx: u32, |
| 2586 | eax: u32, |
| 2587 | eip: u32, |
| 2588 | _cs: i32, |
| 2589 | _eflags: i32, |
| 2590 | esp: u32, |
| 2591 | }, |
| 2592 | }, |
| 2593 | // https://github.com/openbsd/src/blob/42468faed8369d07ae49ae02dd71ec34f59b66cd/sys/arch/amd64/include/signal.h |
| 2594 | .x86_64 => extern struct { |
| 2595 | mcontext: extern struct { |
| 2596 | rdi: u64, |
| 2597 | rsi: u64, |
| 2598 | rdx: u64, |
| 2599 | rcx: u64, |
| 2600 | r8: u64, |
| 2601 | r9: u64, |
| 2602 | r10: u64, |
| 2603 | r11: u64, |
| 2604 | r12: u64, |
| 2605 | r13: u64, |
| 2606 | r14: u64, |
| 2607 | r15: u64, |
| 2608 | rbp: u64, |
| 2609 | rbx: u64, |
| 2610 | rax: u64, |
| 2611 | _gs: i64, |
| 2612 | _fs: i64, |
| 2613 | _es: i64, |
| 2614 | _ds: i64, |
| 2615 | _trapno: i64, |
| 2616 | _err: i64, |
| 2617 | rip: u64, |
| 2618 | _cs: i64, |
| 2619 | _rflags: i64, |
| 2620 | rsp: u64, |
| 2621 | }, |
| 2622 | }, |
| 2623 | else => unreachable, |
| 2624 | }, |
| 2625 | // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/sys/ucontext.h |
| 2626 | .netbsd => extern struct { |
| 2627 | _flags: u32, |
| 2628 | _link: ?*signal_ucontext_t, |
| 2629 | _sigmask: std.c.sigset_t, |
| 2630 | _stack: std.c.stack_t, |
| 2631 | mcontext: switch (native_arch) { |
| 2632 | // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/arm/include/mcontext.h |
| 2633 | .aarch64, .aarch64_be => extern struct { |
| 2634 | x: [30]u64 align(16), |
| 2635 | lr: u64, |
| 2636 | sp: u64, |
| 2637 | pc: u64, |
| 2638 | }, |
| 2639 | // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/alpha/include/mcontext.h |
| 2640 | .alpha => extern struct { |
| 2641 | r: [32]u64, |
| 2642 | pc: u64, |
| 2643 | }, |
| 2644 | // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/arm/include/mcontext.h |
| 2645 | .arm, .armeb => extern struct { |
| 2646 | r: [15]u32 align(8), |
| 2647 | pc: u32, |
| 2648 | }, |
| 2649 | // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/hppa/include/mcontext.h |
| 2650 | .hppa => extern struct { |
| 2651 | r1_19: [19]u32 align(8), |
| 2652 | r20: u32, |
| 2653 | r21: u32, |
| 2654 | r22: u32, |
| 2655 | r23_29: [7]u32, |
| 2656 | r30: u32, |
| 2657 | r31: u32, |
| 2658 | _sar: u32, |
| 2659 | _pcsqh: u32, |
| 2660 | _pcsqt: u32, |
| 2661 | iaoq: [2]u32, |
| 2662 | }, |
| 2663 | // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/m68k/include/mcontext.h |
| 2664 | .m68k => extern struct { |
| 2665 | d: [8]u32, |
| 2666 | a: [8]u32, |
| 2667 | pc: u32, |
| 2668 | }, |
| 2669 | // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/mips/include/mcontext.h |
| 2670 | .mips, .mipsel => extern struct { |
| 2671 | r: [32]u32 align(8), |
| 2672 | _lo: i32, |
| 2673 | _hi: i32, |
| 2674 | _cause: i32, |
| 2675 | pc: u32, |
| 2676 | }, |
| 2677 | // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/mips/include/mcontext.h |
| 2678 | .mips64, .mips64el => @compileError("https://github.com/ziglang/zig/issues/23765#issuecomment-2880386178"), |
| 2679 | // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/powerpc/include/mcontext.h |
| 2680 | .powerpc => extern struct { |
| 2681 | r: [32]u32 align(16), |
| 2682 | _cr: i32, |
| 2683 | lr: u32, |
| 2684 | pc: u32, |
| 2685 | }, |
| 2686 | // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/riscv/include/mcontext.h |
| 2687 | .riscv32, .riscv64 => extern struct { |
| 2688 | ra_sp_gp_tp: [4]usize align(8), |
| 2689 | t0_2: [3]usize, |
| 2690 | s0_1: [2]usize, |
| 2691 | a: [8]usize, |
| 2692 | s2_11: [10]usize, |
| 2693 | t3_6: [4]usize, |
| 2694 | pc: usize, |
| 2695 | }, |
| 2696 | // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/sparc/include/mcontext.h |
| 2697 | .sparc => @compileError("sparc-netbsd mcontext_t missing"), |
| 2698 | .sparc64 => @compileError("sparc64-netbsd mcontext_t missing"), |
| 2699 | // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/sh3/include/mcontext.h |
| 2700 | .sh, .sheb => extern struct { |
| 2701 | _gbr: i32, |
| 2702 | pc: u32, |
| 2703 | _sr: i32, |
| 2704 | _macl: i32, |
| 2705 | _mach: i32, |
| 2706 | pr: u32, |
| 2707 | r14: u32, |
| 2708 | r13_0: [14]u32, |
| 2709 | r15: u32, |
| 2710 | }, |
| 2711 | // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/i386/include/mcontext.h |
| 2712 | .x86 => extern struct { |
| 2713 | _gs: i32, |
| 2714 | _fs: i32, |
| 2715 | _es: i32, |
| 2716 | _ds: i32, |
| 2717 | edi: u32, |
| 2718 | esi: u32, |
| 2719 | ebp: u32, |
| 2720 | esp: u32, |
| 2721 | ebx: u32, |
| 2722 | edx: u32, |
| 2723 | ecx: u32, |
| 2724 | eax: u32, |
| 2725 | _trapno: i32, |
| 2726 | _err: i32, |
| 2727 | eip: u32, |
| 2728 | }, |
| 2729 | // https://github.com/NetBSD/src/blob/861008c62187bf7bc0aac4d81e52ed6eee4d0c74/sys/arch/amd64/include/mcontext.h |
| 2730 | .x86_64 => extern struct { |
| 2731 | rdi: u64, |
| 2732 | rsi: u64, |
| 2733 | rdx: u64, |
| 2734 | rcx: u64, |
| 2735 | r8: u64, |
| 2736 | r9: u64, |
| 2737 | r10: u64, |
| 2738 | r11: u64, |
| 2739 | r12: u64, |
| 2740 | r13: u64, |
| 2741 | r14: u64, |
| 2742 | r15: u64, |
| 2743 | rbp: u64, |
| 2744 | rbx: u64, |
| 2745 | rax: u64, |
| 2746 | _gs: i64, |
| 2747 | _fs: i64, |
| 2748 | _es: i64, |
| 2749 | _ds: i64, |
| 2750 | _trapno: i64, |
| 2751 | _err: i64, |
| 2752 | rip: u64, |
| 2753 | _cs: i64, |
| 2754 | _rflags: i64, |
| 2755 | rsp: u64, |
| 2756 | }, |
| 2757 | else => unreachable, |
| 2758 | }, |
| 2759 | }, |
| 2760 | // https://github.com/DragonFlyBSD/DragonFlyBSD/blob/3de1e9d36269616d22237f19d60a737a41271ab5/sys/sys/_ucontext.h |
| 2761 | .dragonfly => extern struct { |
| 2762 | _sigmask: std.c.sigset_t, |
| 2763 | mcontext: switch (native_arch) { |
| 2764 | // https://github.com/DragonFlyBSD/DragonFlyBSD/blob/3de1e9d36269616d22237f19d60a737a41271ab5/sys/cpu/x86_64/include/ucontext.h |
| 2765 | .x86_64 => extern struct { |
| 2766 | _onstack: i64 align(64), |
| 2767 | rdi: u64, |
| 2768 | rsi: u64, |
| 2769 | rdx: u64, |
| 2770 | rcx: u64, |
| 2771 | r8: u64, |
| 2772 | r9: u64, |
| 2773 | rax: u64, |
| 2774 | rbx: u64, |
| 2775 | rbp: u64, |
| 2776 | r10: u64, |
| 2777 | r11: u64, |
| 2778 | r12: u64, |
| 2779 | r13: u64, |
| 2780 | r14: u64, |
| 2781 | r15: u64, |
| 2782 | _xflags: i64, |
| 2783 | _trapno: i64, |
| 2784 | _addr: i64, |
| 2785 | _flags: i64, |
| 2786 | _err: i64, |
| 2787 | rip: u64, |
| 2788 | _cs: i64, |
| 2789 | _rflags: i64, |
| 2790 | rsp: u64, |
| 2791 | }, |
| 2792 | else => unreachable, |
| 2793 | }, |
| 2794 | }, |
| 2795 | // https://github.com/SerenityOS/serenity/blob/103d6a07de9e28f3c94dfa2351b9af76a49ba6e6/Kernel/API/POSIX/ucontext.h |
| 2796 | .serenity => extern struct { |
| 2797 | _link: ?*signal_ucontext_t, |
| 2798 | _sigmask: std.c.sigset_t, |
| 2799 | _stack: std.c.stack_t, |
| 2800 | mcontext: switch (native_arch) { |
| 2801 | // https://github.com/SerenityOS/serenity/blob/103d6a07de9e28f3c94dfa2351b9af76a49ba6e6/Kernel/Arch/aarch64/mcontext.h |
| 2802 | .aarch64 => extern struct { |
| 2803 | x: [30]u64, |
| 2804 | lr: u64, |
| 2805 | sp: u64, |
| 2806 | pc: u64, |
| 2807 | }, |
| 2808 | // https://github.com/SerenityOS/serenity/blob/103d6a07de9e28f3c94dfa2351b9af76a49ba6e6/Kernel/Arch/riscv64/mcontext.h |
| 2809 | .riscv64 => extern struct { |
| 2810 | ra_sp_gp_tp: [4]u64, |
| 2811 | t0_2: [3]u64, |
| 2812 | s0_1: [2]u64, |
| 2813 | a: [8]u64, |
| 2814 | s2_11: [10]u64, |
| 2815 | t3_6: [4]u64, |
| 2816 | pc: u64, |
| 2817 | }, |
| 2818 | // https://github.com/SerenityOS/serenity/blob/103d6a07de9e28f3c94dfa2351b9af76a49ba6e6/Kernel/Arch/x86_64/mcontext.h |
| 2819 | .x86_64 => extern struct { |
| 2820 | rax: u64, |
| 2821 | rcx: u64, |
| 2822 | rdx: u64, |
| 2823 | rbx: u64, |
| 2824 | rsp: u64, |
| 2825 | rbp: u64, |
| 2826 | rsi: u64, |
| 2827 | rdi: u64, |
| 2828 | rip: u64, |
| 2829 | r8: u64, |
| 2830 | r9: u64, |
| 2831 | r10: u64, |
| 2832 | r11: u64, |
| 2833 | r12: u64, |
| 2834 | r13: u64, |
| 2835 | r14: u64, |
| 2836 | r15: u64, |
| 2837 | }, |
| 2838 | else => unreachable, |
| 2839 | }, |
| 2840 | }, |
| 2841 | // https://github.com/haiku/haiku/blob/47538c534fe0aadc626c09d121773fee8ea10d71/headers/posix/signal.h#L356 |
| 2842 | .haiku => extern struct { |
| 2843 | _link: ?*signal_ucontext_t, |
| 2844 | _sigmask: std.c.sigset_t, |
| 2845 | _stack: std.c.stack_t, |
| 2846 | mcontext: switch (native_arch) { |
| 2847 | // https://github.com/haiku/haiku/blob/47538c534fe0aadc626c09d121773fee8ea10d71/headers/posix/arch/arm/signal.h |
| 2848 | .arm => extern struct { |
| 2849 | r: [15]u32 align(8), |
| 2850 | pc: u32, |
| 2851 | }, |
| 2852 | // https://github.com/haiku/haiku/blob/47538c534fe0aadc626c09d121773fee8ea10d71/headers/posix/arch/arm64/signal.h |
| 2853 | .aarch64 => extern struct { |
| 2854 | x: [30]u64 align(16), |
| 2855 | lr: u64, |
| 2856 | sp: u64, |
| 2857 | pc: u64, |
| 2858 | }, |
| 2859 | // https://github.com/haiku/haiku/blob/47538c534fe0aadc626c09d121773fee8ea10d71/headers/posix/arch/riscv64/signal.h |
| 2860 | .riscv64 => extern struct { |
| 2861 | ra_sp_gp_tp: [4]u64, |
| 2862 | t0_2: [3]u64, |
| 2863 | s0_1: [2]u64, |
| 2864 | a: [8]u64, |
| 2865 | s2_11: [10]u64, |
| 2866 | t3_6: [4]u64, |
| 2867 | pc: u64, |
| 2868 | }, |
| 2869 | // https://github.com/haiku/haiku/blob/47538c534fe0aadc626c09d121773fee8ea10d71/headers/posix/arch/x86/signal.h |
| 2870 | .x86 => extern struct { |
| 2871 | eip: u32, |
| 2872 | _eflags: u32, |
| 2873 | eax: u32, |
| 2874 | ecx: u32, |
| 2875 | edx: u32, |
| 2876 | esp: u32, |
| 2877 | ebp: u32, |
| 2878 | _reserved: u32, |
| 2879 | _xregs: extern struct { |
| 2880 | _fp_control: u16, |
| 2881 | _fp_status: u16, |
| 2882 | _fp_tag: u16, |
| 2883 | _fp_opcode: u16, |
| 2884 | _fp_eip: u32, |
| 2885 | _fp_cs: u16, |
| 2886 | _reserved1: u16, |
| 2887 | _fp_datap: u32, |
| 2888 | _fp_ds: u16, |
| 2889 | _reserved2: u16, |
| 2890 | _mxcsr: u32, |
| 2891 | _mxcsr_mask: u32, |
| 2892 | _mmx: [8][16]u8, |
| 2893 | _xmmx: [8][16]u8, |
| 2894 | _reserved3: [176]u8, |
| 2895 | _fault_address: u32, |
| 2896 | _error_code: u32, |
| 2897 | _cs: u16, |
| 2898 | _ds: u16, |
| 2899 | _es: u16, |
| 2900 | _fs: u16, |
| 2901 | _gs: u16, |
| 2902 | _ss: u16, |
| 2903 | _trap_number: u8, |
| 2904 | _reserved4: [27]u8, |
| 2905 | _format: u32, |
| 2906 | }, |
| 2907 | edi: u32, |
| 2908 | esi: u32, |
| 2909 | ebx: u32, |
| 2910 | }, |
| 2911 | // https://github.com/haiku/haiku/blob/47538c534fe0aadc626c09d121773fee8ea10d71/headers/posix/arch/x86_64/signal.h |
| 2912 | .x86_64 => extern struct { |
| 2913 | rax: u64, |
| 2914 | rbx: u64, |
| 2915 | rcx: u64, |
| 2916 | rdx: u64, |
| 2917 | rdi: u64, |
| 2918 | rsi: u64, |
| 2919 | rbp: u64, |
| 2920 | r8: u64, |
| 2921 | r9: u64, |
| 2922 | r10: u64, |
| 2923 | r11: u64, |
| 2924 | r12: u64, |
| 2925 | r13: u64, |
| 2926 | r14: u64, |
| 2927 | r15: u64, |
| 2928 | rsp: u64, |
| 2929 | rip: u64, |
| 2930 | }, |
| 2931 | else => unreachable, |
| 2932 | }, |
| 2933 | }, |
| 2934 | else => void, |
| 2935 | }; |
| 2936 | |
| 2937 | const std = @import("../std.zig"); |
| 2938 | const root = @import("root"); |
| 2939 | const builtin = @import("builtin"); |
| 2940 | const native_arch = @import("builtin").target.cpu.arch; |
| 2941 | const native_os = @import("builtin").target.os.tag; |