| ... | ... | @@ -8,6 +8,7 @@ else switch (native_arch) { |
| 8 | 8 | .arm, .armeb, .thumb, .thumbeb => Arm, |
| 9 | 9 | .loongarch32, .loongarch64 => LoongArch, |
| 10 | 10 | .riscv32, .riscv32be, .riscv64, .riscv64be => Riscv, |
| 11 | .s390x => S390x, |
| 11 | 12 | .x86 => X86, |
| 12 | 13 | .x86_64 => X86_64, |
| 13 | 14 | else => noreturn, |
| ... | ... | @@ -189,6 +190,17 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native { |
| 189 | 190 | }, |
| 190 | 191 | else => null, |
| 191 | 192 | }, |
| 193 | .s390x => switch (builtin.os.tag) { |
| 194 | .linux => .{ |
| 195 | .r = uc.mcontext.gregs, |
| 196 | .f = uc.mcontext.fregs, |
| 197 | .psw = .{ |
| 198 | .mask = uc.mcontext.psw.mask, |
| 199 | .addr = uc.mcontext.psw.addr, |
| 200 | }, |
| 201 | }, |
| 202 | else => null, |
| 203 | }, |
| 192 | 204 | else => null, |
| 193 | 205 | }; |
| 194 | 206 | } |
| ... | ... | @@ -677,6 +689,81 @@ pub const Riscv = extern struct { |
| 677 | 689 | } |
| 678 | 690 | }; |
| 679 | 691 | |
| 692 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| 693 | pub const S390x = extern struct { |
| 694 | /// The numbered general-purpose registers r0 - r15. |
| 695 | r: [16]u64, |
| 696 | /// The numbered floating-point registers f0 - f15. Yes, really - they can be used in DWARF CFI. |
| 697 | f: [16]f64, |
| 698 | /// The program counter. |
| 699 | psw: extern struct { |
| 700 | mask: u64, |
| 701 | addr: u64, |
| 702 | }, |
| 703 | |
| 704 | pub inline fn current() S390x { |
| 705 | var ctx: S390x = undefined; |
| 706 | asm volatile ( |
| 707 | \\ stmg %%r0, %%r15, 0(%%r2) |
| 708 | \\ std %%f0, 128(%%r2) |
| 709 | \\ std %%f1, 136(%%r2) |
| 710 | \\ std %%f2, 144(%%r2) |
| 711 | \\ std %%f3, 152(%%r2) |
| 712 | \\ std %%f4, 160(%%r2) |
| 713 | \\ std %%f5, 168(%%r2) |
| 714 | \\ std %%f6, 176(%%r2) |
| 715 | \\ std %%f7, 184(%%r2) |
| 716 | \\ std %%f8, 192(%%r2) |
| 717 | \\ std %%f9, 200(%%r2) |
| 718 | \\ std %%f10, 208(%%r2) |
| 719 | \\ std %%f11, 216(%%r2) |
| 720 | \\ std %%f12, 224(%%r2) |
| 721 | \\ std %%f13, 232(%%r2) |
| 722 | \\ std %%f14, 240(%%r2) |
| 723 | \\ std %%f15, 248(%%r2) |
| 724 | \\ epsw %%r0, %%r1 |
| 725 | \\ stm %%r0, %%r1, 256(%%r2) |
| 726 | \\ larl %%r0, . |
| 727 | \\ stg %%r0, 264(%%r2) |
| 728 | \\ lg %%r0, 0(%%r2) |
| 729 | \\ lg %%r1, 8(%%r2) |
| 730 | : |
| 731 | : [gprs] "{r2}" (&ctx), |
| 732 | : .{ .memory = true }); |
| 733 | return ctx; |
| 734 | } |
| 735 | |
| 736 | pub fn dwarfRegisterBytes(ctx: *S390x, register_num: u16) DwarfRegisterError![]u8 { |
| 737 | switch (register_num) { |
| 738 | 0...15 => return @ptrCast(&ctx.r[register_num]), |
| 739 | // Why??? |
| 740 | 16 => return @ptrCast(&ctx.f[0]), |
| 741 | 17 => return @ptrCast(&ctx.f[2]), |
| 742 | 18 => return @ptrCast(&ctx.f[4]), |
| 743 | 19 => return @ptrCast(&ctx.f[6]), |
| 744 | 20 => return @ptrCast(&ctx.f[1]), |
| 745 | 21 => return @ptrCast(&ctx.f[3]), |
| 746 | 22 => return @ptrCast(&ctx.f[5]), |
| 747 | 23 => return @ptrCast(&ctx.f[7]), |
| 748 | 24 => return @ptrCast(&ctx.f[8]), |
| 749 | 25 => return @ptrCast(&ctx.f[10]), |
| 750 | 26 => return @ptrCast(&ctx.f[12]), |
| 751 | 27 => return @ptrCast(&ctx.f[14]), |
| 752 | 28 => return @ptrCast(&ctx.f[9]), |
| 753 | 29 => return @ptrCast(&ctx.f[11]), |
| 754 | 30 => return @ptrCast(&ctx.f[13]), |
| 755 | 31 => return @ptrCast(&ctx.f[15]), |
| 756 | 64 => return @ptrCast(&ctx.psw.mask), |
| 757 | 65 => return @ptrCast(&ctx.psw.addr), |
| 758 | |
| 759 | 48...63 => return error.UnsupportedRegister, // a0 - a15 |
| 760 | 68...83 => return error.UnsupportedRegister, // v16 - v31 |
| 761 | |
| 762 | else => return error.InvalidRegister, |
| 763 | } |
| 764 | } |
| 765 | }; |
| 766 | |
| 680 | 767 | const signal_ucontext_t = switch (native_os) { |
| 681 | 768 | .linux => std.os.linux.ucontext_t, |
| 682 | 769 | .emscripten => std.os.emscripten.ucontext_t, |