| ... | @@ -8,6 +8,8 @@ else switch (native_arch) { | ... | @@ -8,6 +8,8 @@ else switch (native_arch) { |
| 8 | .arm, .armeb, .thumb, .thumbeb => Arm, | 8 | .arm, .armeb, .thumb, .thumbeb => Arm, |
| 9 | .hexagon => Hexagon, | 9 | .hexagon => Hexagon, |
| 10 | .loongarch32, .loongarch64 => LoongArch, | 10 | .loongarch32, .loongarch64 => LoongArch, |
| | 11 | .mips, .mipsel, .mips64, .mips64el => Mips, |
| | 12 | .powerpc, .powerpcle, .powerpc64, .powerpc64le => Powerpc, |
| 11 | .riscv32, .riscv32be, .riscv64, .riscv64be => Riscv, | 13 | .riscv32, .riscv32be, .riscv64, .riscv64be => Riscv, |
| 12 | .s390x => S390x, | 14 | .s390x => S390x, |
| 13 | .x86 => X86, | 15 | .x86 => X86, |
| ... | @@ -196,6 +198,33 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native { | ... | @@ -196,6 +198,33 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native { |
| 196 | }, | 198 | }, |
| 197 | else => null, | 199 | else => null, |
| 198 | }, | 200 | }, |
| | 201 | .mips, .mipsel => switch (builtin.os.tag) { |
| | 202 | // The O32 kABI uses 64-bit fields for some reason... |
| | 203 | .linux => .{ |
| | 204 | .r = s: { |
| | 205 | var regs: [32]Mips.Gpr = undefined; |
| | 206 | for (uc.mcontext.regs, 0..) |r, i| regs[i] = @truncate(r); // includes r0 (hardwired zero) |
| | 207 | break :s regs; |
| | 208 | }, |
| | 209 | .pc = @truncate(uc.mcontext.pc), |
| | 210 | }, |
| | 211 | else => null, |
| | 212 | }, |
| | 213 | .mips64, .mips64el => switch (builtin.os.tag) { |
| | 214 | .linux => .{ |
| | 215 | .r = uc.mcontext.regs, // includes r0 (hardwired zero) |
| | 216 | .pc = uc.mcontext.pc, |
| | 217 | }, |
| | 218 | else => null, |
| | 219 | }, |
| | 220 | .powerpc, .powerpcle, .powerpc64, .powerpc64le => switch (builtin.os.tag) { |
| | 221 | .linux => .{ |
| | 222 | .r = uc.mcontext.gp_regs[0..32].*, |
| | 223 | .pc = uc.mcontext.gp_regs[32], |
| | 224 | .lr = uc.mcontext.gp_regs[36], |
| | 225 | }, |
| | 226 | else => null, |
| | 227 | }, |
| 199 | .riscv32, .riscv64 => switch (builtin.os.tag) { | 228 | .riscv32, .riscv64 => switch (builtin.os.tag) { |
| 200 | .linux => .{ | 229 | .linux => .{ |
| 201 | .r = [1]usize{0} ++ uc.mcontext.gregs[1..].*, // r0 position is used for pc; replace with zero | 230 | .r = [1]usize{0} ++ uc.mcontext.gregs[1..].*, // r0 position is used for pc; replace with zero |
| ... | @@ -210,7 +239,6 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native { | ... | @@ -210,7 +239,6 @@ pub fn fromPosixSignalContext(ctx_ptr: ?*const anyopaque) ?Native { |
| 210 | .s390x => switch (builtin.os.tag) { | 239 | .s390x => switch (builtin.os.tag) { |
| 211 | .linux => .{ | 240 | .linux => .{ |
| 212 | .r = uc.mcontext.gregs, | 241 | .r = uc.mcontext.gregs, |
| 213 | .f = uc.mcontext.fregs, | | |
| 214 | .psw = .{ | 242 | .psw = .{ |
| 215 | .mask = uc.mcontext.psw.mask, | 243 | .mask = uc.mcontext.psw.mask, |
| 216 | .addr = uc.mcontext.psw.addr, | 244 | .addr = uc.mcontext.psw.addr, |
| ... | @@ -269,7 +297,7 @@ pub fn fromWindowsContext(ctx: *const std.os.windows.CONTEXT) Native { | ... | @@ -269,7 +297,7 @@ pub fn fromWindowsContext(ctx: *const std.os.windows.CONTEXT) Native { |
| 269 | }; | 297 | }; |
| 270 | } | 298 | } |
| 271 | | 299 | |
| 272 | pub const X86 = struct { | 300 | const X86 = struct { |
| 273 | /// The first 8 registers here intentionally match the order of registers in the x86 instruction | 301 | /// The first 8 registers here intentionally match the order of registers in the x86 instruction |
| 274 | /// encoding. This order is inherited by the PUSHA instruction and the DWARF register mappings, | 302 | /// encoding. This order is inherited by the PUSHA instruction and the DWARF register mappings, |
| 275 | /// among other things. | 303 | /// among other things. |
| ... | @@ -313,7 +341,7 @@ pub const X86 = struct { | ... | @@ -313,7 +341,7 @@ pub const X86 = struct { |
| 313 | // x86-macos is a deprecated target which is not supported by the Zig Standard Library. | 341 | // x86-macos is a deprecated target which is not supported by the Zig Standard Library. |
| 314 | 0...8 => return @ptrCast(&ctx.gprs.values[register_num]), | 342 | 0...8 => return @ptrCast(&ctx.gprs.values[register_num]), |
| 315 | | 343 | |
| 316 | 9 => return error.UnsupportedRegister, // rflags | 344 | 9 => return error.UnsupportedRegister, // eflags |
| 317 | 11...18 => return error.UnsupportedRegister, // st0 - st7 | 345 | 11...18 => return error.UnsupportedRegister, // st0 - st7 |
| 318 | 21...28 => return error.UnsupportedRegister, // xmm0 - xmm7 | 346 | 21...28 => return error.UnsupportedRegister, // xmm0 - xmm7 |
| 319 | 29...36 => return error.UnsupportedRegister, // mm0 - mm7 | 347 | 29...36 => return error.UnsupportedRegister, // mm0 - mm7 |
| ... | @@ -321,14 +349,14 @@ pub const X86 = struct { | ... | @@ -321,14 +349,14 @@ pub const X86 = struct { |
| 321 | 40...45 => return error.UnsupportedRegister, // es, cs, ss, ds, fs, gs | 349 | 40...45 => return error.UnsupportedRegister, // es, cs, ss, ds, fs, gs |
| 322 | 48 => return error.UnsupportedRegister, // tr | 350 | 48 => return error.UnsupportedRegister, // tr |
| 323 | 49 => return error.UnsupportedRegister, // ldtr | 351 | 49 => return error.UnsupportedRegister, // ldtr |
| 324 | 93...94 => return error.UnsupportedRegister, // fs.base, gs.base | 352 | 93...100 => return error.UnsupportedRegister, // k0 - k7 (AVX-512) |
| 325 | | 353 | |
| 326 | else => return error.InvalidRegister, | 354 | else => return error.InvalidRegister, |
| 327 | } | 355 | } |
| 328 | } | 356 | } |
| 329 | }; | 357 | }; |
| 330 | | 358 | |
| 331 | pub const X86_64 = struct { | 359 | const X86_64 = struct { |
| 332 | /// The order here intentionally matches the order of the DWARF register mappings. It's unclear | 360 | /// The order here intentionally matches the order of the DWARF register mappings. It's unclear |
| 333 | /// where those mappings actually originated from---the ordering of the first 4 registers seems | 361 | /// where those mappings actually originated from---the ordering of the first 4 registers seems |
| 334 | /// quite unusual---but it is currently convenient for us to match DWARF. | 362 | /// quite unusual---but it is currently convenient for us to match DWARF. |
| ... | @@ -389,13 +417,16 @@ pub const X86_64 = struct { | ... | @@ -389,13 +417,16 @@ pub const X86_64 = struct { |
| 389 | 64 => return error.UnsupportedRegister, // mxcsr | 417 | 64 => return error.UnsupportedRegister, // mxcsr |
| 390 | 65 => return error.UnsupportedRegister, // fcw | 418 | 65 => return error.UnsupportedRegister, // fcw |
| 391 | 66 => return error.UnsupportedRegister, // fsw | 419 | 66 => return error.UnsupportedRegister, // fsw |
| | 420 | 67...82 => return error.UnsupportedRegister, // xmm16 - xmm31 (AVX-512) |
| | 421 | 118...125 => return error.UnsupportedRegister, // k0 - k7 (AVX-512) |
| | 422 | 130...145 => return error.UnsupportedRegister, // r16 - r31 (APX) |
| 392 | | 423 | |
| 393 | else => return error.InvalidRegister, | 424 | else => return error.InvalidRegister, |
| 394 | } | 425 | } |
| 395 | } | 426 | } |
| 396 | }; | 427 | }; |
| 397 | | 428 | |
| 398 | pub const Arm = struct { | 429 | const Arm = struct { |
| 399 | /// The numbered general-purpose registers R0 - R15. | 430 | /// The numbered general-purpose registers R0 - R15. |
| 400 | r: [16]u32, | 431 | r: [16]u32, |
| 401 | | 432 | |
| ... | @@ -449,7 +480,7 @@ pub const Arm = struct { | ... | @@ -449,7 +480,7 @@ pub const Arm = struct { |
| 449 | }; | 480 | }; |
| 450 | | 481 | |
| 451 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. | 482 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| 452 | pub const Aarch64 = extern struct { | 483 | const Aarch64 = extern struct { |
| 453 | /// The numbered general-purpose registers X0 - X30. | 484 | /// The numbered general-purpose registers X0 - X30. |
| 454 | x: [31]u64, | 485 | x: [31]u64, |
| 455 | sp: u64, | 486 | sp: u64, |
| ... | @@ -492,13 +523,13 @@ pub const Aarch64 = extern struct { | ... | @@ -492,13 +523,13 @@ pub const Aarch64 = extern struct { |
| 492 | 31 => return @ptrCast(&ctx.sp), | 523 | 31 => return @ptrCast(&ctx.sp), |
| 493 | 32 => return @ptrCast(&ctx.pc), | 524 | 32 => return @ptrCast(&ctx.pc), |
| 494 | | 525 | |
| 495 | 33 => return error.UnsupportedRegister, // ELF_mode | 526 | 33 => return error.UnsupportedRegister, // ELR_mode |
| 496 | 34 => return error.UnsupportedRegister, // RA_SIGN_STATE | 527 | 34 => return error.UnsupportedRegister, // RA_SIGN_STATE |
| 497 | 35 => return error.UnsupportedRegister, // TPIDRRO_ELO | 528 | 35 => return error.UnsupportedRegister, // TPIDRRO_ELO |
| 498 | 36 => return error.UnsupportedRegister, // RPIDR_ELO | 529 | 36 => return error.UnsupportedRegister, // TPIDR_ELO |
| 499 | 37 => return error.UnsupportedRegister, // RPIDR_EL1 | 530 | 37 => return error.UnsupportedRegister, // TPIDR_EL1 |
| 500 | 38 => return error.UnsupportedRegister, // RPIDR_EL2 | 531 | 38 => return error.UnsupportedRegister, // TPIDR_EL2 |
| 501 | 39 => return error.UnsupportedRegister, // RPIDR_EL3 | 532 | 39 => return error.UnsupportedRegister, // TPIDR_EL3 |
| 502 | 46 => return error.UnsupportedRegister, // VG | 533 | 46 => return error.UnsupportedRegister, // VG |
| 503 | 47 => return error.UnsupportedRegister, // FFR | 534 | 47 => return error.UnsupportedRegister, // FFR |
| 504 | 48...63 => return error.UnsupportedRegister, // P0 - P15 | 535 | 48...63 => return error.UnsupportedRegister, // P0 - P15 |
| ... | @@ -511,7 +542,7 @@ pub const Aarch64 = extern struct { | ... | @@ -511,7 +542,7 @@ pub const Aarch64 = extern struct { |
| 511 | }; | 542 | }; |
| 512 | | 543 | |
| 513 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. | 544 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| 514 | pub const Hexagon = extern struct { | 545 | const Hexagon = extern struct { |
| 515 | /// The numbered general-purpose registers r0 - r31. | 546 | /// The numbered general-purpose registers r0 - r31. |
| 516 | r: [32]u32, | 547 | r: [32]u32, |
| 517 | pc: u32, | 548 | pc: u32, |
| ... | @@ -579,14 +610,16 @@ pub const Hexagon = extern struct { | ... | @@ -579,14 +610,16 @@ pub const Hexagon = extern struct { |
| 579 | }; | 610 | }; |
| 580 | | 611 | |
| 581 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. | 612 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| 582 | pub const LoongArch = extern struct { | 613 | const LoongArch = extern struct { |
| 583 | /// The numbered general-purpose registers r0 - r31. r0 must be zero. | 614 | /// The numbered general-purpose registers r0 - r31. r0 must be zero. |
| 584 | r: [32]usize, | 615 | r: [32]Gpr, |
| 585 | pc: usize, | 616 | pc: Gpr, |
| | 617 | |
| | 618 | pub const Gpr = if (builtin.target.cpu.arch == .loongarch64) u64 else u32; |
| 586 | | 619 | |
| 587 | pub inline fn current() LoongArch { | 620 | pub inline fn current() LoongArch { |
| 588 | var ctx: LoongArch = undefined; | 621 | var ctx: LoongArch = undefined; |
| 589 | asm volatile (if (@sizeOf(usize) == 8) | 622 | asm volatile (if (Gpr == u64) |
| 590 | \\ st.d $zero, $t0, 0 | 623 | \\ st.d $zero, $t0, 0 |
| 591 | \\ st.d $ra, $t0, 8 | 624 | \\ st.d $ra, $t0, 8 |
| 592 | \\ st.d $tp, $t0, 16 | 625 | \\ st.d $tp, $t0, 16 |
| ... | @@ -669,7 +702,9 @@ pub const LoongArch = extern struct { | ... | @@ -669,7 +702,9 @@ pub const LoongArch = extern struct { |
| 669 | pub fn dwarfRegisterBytes(ctx: *LoongArch, register_num: u16) DwarfRegisterError![]u8 { | 702 | pub fn dwarfRegisterBytes(ctx: *LoongArch, register_num: u16) DwarfRegisterError![]u8 { |
| 670 | switch (register_num) { | 703 | switch (register_num) { |
| 671 | 0...31 => return @ptrCast(&ctx.r[register_num]), | 704 | 0...31 => return @ptrCast(&ctx.r[register_num]), |
| 672 | 32 => return @ptrCast(&ctx.pc), | 705 | 64 => return @ptrCast(&ctx.pc), |
| | 706 | |
| | 707 | 32...63 => return error.UnsupportedRegister, // f0 - f31 |
| 673 | | 708 | |
| 674 | else => return error.InvalidRegister, | 709 | else => return error.InvalidRegister, |
| 675 | } | 710 | } |
| ... | @@ -677,14 +712,294 @@ pub const LoongArch = extern struct { | ... | @@ -677,14 +712,294 @@ pub const LoongArch = extern struct { |
| 677 | }; | 712 | }; |
| 678 | | 713 | |
| 679 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. | 714 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| 680 | pub const Riscv = extern struct { | 715 | const Mips = extern struct { |
| 681 | /// The numbered general-purpose registers r0 - r31. r0 must be zero. | 716 | /// The numbered general-purpose registers r0 - r31. r0 must be zero. |
| 682 | r: [32]usize, | 717 | r: [32]Gpr, |
| 683 | pc: usize, | 718 | pc: Gpr, |
| | 719 | |
| | 720 | pub const Gpr = if (builtin.target.cpu.arch.isMIPS64()) u64 else u32; |
| | 721 | |
| | 722 | pub inline fn current() Mips { |
| | 723 | var ctx: Mips = undefined; |
| | 724 | asm volatile (if (Gpr == u64) |
| | 725 | \\ .set push |
| | 726 | \\ .set noat |
| | 727 | \\ .set noreorder |
| | 728 | \\ .set nomacro |
| | 729 | \\ sd $zero, 0($t0) |
| | 730 | \\ sd $at, 8($t0) |
| | 731 | \\ sd $v0, 16($t0) |
| | 732 | \\ sd $v1, 24($t0) |
| | 733 | \\ sd $a0, 32($t0) |
| | 734 | \\ sd $a1, 40($t0) |
| | 735 | \\ sd $a2, 48($t0) |
| | 736 | \\ sd $a3, 56($t0) |
| | 737 | \\ sd $a4, 64($t0) |
| | 738 | \\ sd $a5, 72($t0) |
| | 739 | \\ sd $a6, 80($t0) |
| | 740 | \\ sd $a7, 88($t0) |
| | 741 | \\ sd $t0, 96($t0) |
| | 742 | \\ sd $t1, 104($t0) |
| | 743 | \\ sd $t2, 112($t0) |
| | 744 | \\ sd $t3, 120($t0) |
| | 745 | \\ sd $s0, 128($t0) |
| | 746 | \\ sd $s1, 136($t0) |
| | 747 | \\ sd $s2, 144($t0) |
| | 748 | \\ sd $s3, 152($t0) |
| | 749 | \\ sd $s4, 160($t0) |
| | 750 | \\ sd $s5, 168($t0) |
| | 751 | \\ sd $s6, 176($t0) |
| | 752 | \\ sd $s7, 184($t0) |
| | 753 | \\ sd $t8, 192($t0) |
| | 754 | \\ sd $t9, 200($t0) |
| | 755 | \\ sd $k0, 208($t0) |
| | 756 | \\ sd $k1, 216($t0) |
| | 757 | \\ sd $gp, 224($t0) |
| | 758 | \\ sd $sp, 232($t0) |
| | 759 | \\ sd $fp, 240($t0) |
| | 760 | \\ sd $ra, 248($t0) |
| | 761 | \\ bal 1f |
| | 762 | \\1: |
| | 763 | \\ sd $ra, 256($t0) |
| | 764 | \\ ld $ra, 248($t0) |
| | 765 | \\ .set pop |
| | 766 | else |
| | 767 | \\ .set push |
| | 768 | \\ .set noat |
| | 769 | \\ .set noreorder |
| | 770 | \\ .set nomacro |
| | 771 | \\ sw $zero, 0($t4) |
| | 772 | \\ sw $at, 4($t4) |
| | 773 | \\ sw $v0, 8($t4) |
| | 774 | \\ sw $v1, 12($t4) |
| | 775 | \\ sw $a0, 16($t4) |
| | 776 | \\ sw $a1, 20($t4) |
| | 777 | \\ sw $a2, 24($t4) |
| | 778 | \\ sw $a3, 28($t4) |
| | 779 | \\ sw $t0, 32($t4) |
| | 780 | \\ sw $t1, 36($t4) |
| | 781 | \\ sw $t2, 40($t4) |
| | 782 | \\ sw $t3, 44($t4) |
| | 783 | \\ sw $t4, 48($t4) |
| | 784 | \\ sw $t5, 52($t4) |
| | 785 | \\ sw $t6, 56($t4) |
| | 786 | \\ sw $t7, 60($t4) |
| | 787 | \\ sw $s0, 64($t4) |
| | 788 | \\ sw $s1, 68($t4) |
| | 789 | \\ sw $s2, 72($t4) |
| | 790 | \\ sw $s3, 76($t4) |
| | 791 | \\ sw $s4, 80($t4) |
| | 792 | \\ sw $s5, 84($t4) |
| | 793 | \\ sw $s6, 88($t4) |
| | 794 | \\ sw $s7, 92($t4) |
| | 795 | \\ sw $t8, 96($t4) |
| | 796 | \\ sw $t9, 100($t4) |
| | 797 | \\ sw $k0, 104($t4) |
| | 798 | \\ sw $k1, 108($t4) |
| | 799 | \\ sw $gp, 112($t4) |
| | 800 | \\ sw $sp, 116($t4) |
| | 801 | \\ sw $fp, 120($t4) |
| | 802 | \\ sw $ra, 124($t4) |
| | 803 | \\ bal 1f |
| | 804 | \\1: |
| | 805 | \\ sw $ra, 128($t4) |
| | 806 | \\ lw $ra, 124($t4) |
| | 807 | \\ .set pop |
| | 808 | : |
| | 809 | : [gprs] "{$12}" (&ctx), |
| | 810 | : .{ .memory = true }); |
| | 811 | return ctx; |
| | 812 | } |
| | 813 | |
| | 814 | pub fn dwarfRegisterBytes(ctx: *Mips, register_num: u16) DwarfRegisterError![]u8 { |
| | 815 | switch (register_num) { |
| | 816 | 0...31 => return @ptrCast(&ctx.r[register_num]), |
| | 817 | 66 => return @ptrCast(&ctx.pc), |
| | 818 | |
| | 819 | // Who the hell knows what numbers exist for this architecture? What's an ABI |
| | 820 | // specification anyway? We don't need that nonsense. |
| | 821 | 32...63 => return error.UnsupportedRegister, // f0 - f31, w0 - w31 |
| | 822 | 64 => return error.UnsupportedRegister, // hi0 (ac0) |
| | 823 | 65 => return error.UnsupportedRegister, // lo0 (ac0) |
| | 824 | 176 => return error.UnsupportedRegister, // hi1 (ac1) |
| | 825 | 177 => return error.UnsupportedRegister, // lo1 (ac1) |
| | 826 | 178 => return error.UnsupportedRegister, // hi2 (ac2) |
| | 827 | 179 => return error.UnsupportedRegister, // lo2 (ac2) |
| | 828 | 180 => return error.UnsupportedRegister, // hi3 (ac3) |
| | 829 | 181 => return error.UnsupportedRegister, // lo3 (ac3) |
| | 830 | |
| | 831 | else => return error.InvalidRegister, |
| | 832 | } |
| | 833 | } |
| | 834 | }; |
| | 835 | |
| | 836 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| | 837 | const Powerpc = extern struct { |
| | 838 | /// The numbered general-purpose registers r0 - r31. |
| | 839 | r: [32]Gpr, |
| | 840 | pc: Gpr, |
| | 841 | lr: Gpr, |
| | 842 | |
| | 843 | pub const Gpr = if (builtin.target.cpu.arch.isPowerPC64()) u64 else u32; |
| | 844 | |
| | 845 | pub inline fn current() Powerpc { |
| | 846 | var ctx: Powerpc = undefined; |
| | 847 | asm volatile (if (Gpr == u64) |
| | 848 | \\ std 0, 0(10) |
| | 849 | \\ std 1, 8(10) |
| | 850 | \\ std 2, 16(10) |
| | 851 | \\ std 3, 24(10) |
| | 852 | \\ std 4, 32(10) |
| | 853 | \\ std 5, 40(10) |
| | 854 | \\ std 6, 48(10) |
| | 855 | \\ std 7, 56(10) |
| | 856 | \\ std 8, 64(10) |
| | 857 | \\ std 9, 72(10) |
| | 858 | \\ std 10, 80(10) |
| | 859 | \\ std 11, 88(10) |
| | 860 | \\ std 12, 96(10) |
| | 861 | \\ std 13, 104(10) |
| | 862 | \\ std 14, 112(10) |
| | 863 | \\ std 15, 120(10) |
| | 864 | \\ std 16, 128(10) |
| | 865 | \\ std 17, 136(10) |
| | 866 | \\ std 18, 144(10) |
| | 867 | \\ std 19, 152(10) |
| | 868 | \\ std 20, 160(10) |
| | 869 | \\ std 21, 168(10) |
| | 870 | \\ std 22, 176(10) |
| | 871 | \\ std 23, 184(10) |
| | 872 | \\ std 24, 192(10) |
| | 873 | \\ std 25, 200(10) |
| | 874 | \\ std 26, 208(10) |
| | 875 | \\ std 27, 216(10) |
| | 876 | \\ std 28, 224(10) |
| | 877 | \\ std 29, 232(10) |
| | 878 | \\ std 30, 240(10) |
| | 879 | \\ std 31, 248(10) |
| | 880 | \\ mflr 8 |
| | 881 | \\ std 8, 264(10) |
| | 882 | \\ bl 1f |
| | 883 | \\1: |
| | 884 | \\ mflr 8 |
| | 885 | \\ std 8, 256(10) |
| | 886 | \\ ld 8, 64(10) |
| | 887 | else |
| | 888 | \\ stw 0, 0(10) |
| | 889 | \\ stw 1, 4(10) |
| | 890 | \\ stw 2, 8(10) |
| | 891 | \\ stw 3, 12(10) |
| | 892 | \\ stw 4, 16(10) |
| | 893 | \\ stw 5, 20(10) |
| | 894 | \\ stw 6, 24(10) |
| | 895 | \\ stw 7, 28(10) |
| | 896 | \\ stw 8, 32(10) |
| | 897 | \\ stw 9, 36(10) |
| | 898 | \\ stw 10, 40(10) |
| | 899 | \\ stw 11, 44(10) |
| | 900 | \\ stw 12, 48(10) |
| | 901 | \\ stw 13, 52(10) |
| | 902 | \\ stw 14, 56(10) |
| | 903 | \\ stw 15, 60(10) |
| | 904 | \\ stw 16, 64(10) |
| | 905 | \\ stw 17, 68(10) |
| | 906 | \\ stw 18, 72(10) |
| | 907 | \\ stw 19, 76(10) |
| | 908 | \\ stw 20, 80(10) |
| | 909 | \\ stw 21, 84(10) |
| | 910 | \\ stw 22, 88(10) |
| | 911 | \\ stw 23, 92(10) |
| | 912 | \\ stw 24, 96(10) |
| | 913 | \\ stw 25, 100(10) |
| | 914 | \\ stw 26, 104(10) |
| | 915 | \\ stw 27, 108(10) |
| | 916 | \\ stw 28, 112(10) |
| | 917 | \\ stw 29, 116(10) |
| | 918 | \\ stw 30, 120(10) |
| | 919 | \\ stw 31, 124(10) |
| | 920 | \\ mflr 8 |
| | 921 | \\ stw 8, 132(10) |
| | 922 | \\ bl 1f |
| | 923 | \\1: |
| | 924 | \\ mflr 8 |
| | 925 | \\ stw 8, 128(10) |
| | 926 | \\ lwz 8, 32(10) |
| | 927 | : |
| | 928 | : [gprs] "{r10}" (&ctx), |
| | 929 | : .{ .lr = true, .memory = true }); |
| | 930 | return ctx; |
| | 931 | } |
| | 932 | |
| | 933 | pub fn dwarfRegisterBytes(ctx: *Powerpc, register_num: u16) DwarfRegisterError![]u8 { |
| | 934 | // References: |
| | 935 | // |
| | 936 | // * System V Application Binary Interface - PowerPC Processor Supplement §3-46 |
| | 937 | // * Power Architecture 32-bit Application Binary Interface Supplement 1.0 - Linux & Embedded §3.4 |
| | 938 | // * 64-bit ELF V2 ABI Specification - Power Architecture Revision 1.5 §2.4 |
| | 939 | // * ??? AIX? |
| | 940 | // |
| | 941 | // Are we having fun yet? |
| | 942 | |
| | 943 | if (Gpr == u64) switch (register_num) { |
| | 944 | 65 => return @ptrCast(&ctx.lr), // lr |
| | 945 | |
| | 946 | 66 => return error.UnsupportedRegister, // ctr |
| | 947 | 68...75 => return error.UnsupportedRegister, // cr0 - cr7 |
| | 948 | 76 => return error.UnsupportedRegister, // xer |
| | 949 | 77...108 => return error.UnsupportedRegister, // vr0 - vr31 |
| | 950 | 109 => return error.UnsupportedRegister, // vrsave (LLVM) |
| | 951 | 110 => return error.UnsupportedRegister, // vscr |
| | 952 | 114 => return error.UnsupportedRegister, // tfhar |
| | 953 | 115 => return error.UnsupportedRegister, // tfiar |
| | 954 | 116 => return error.UnsupportedRegister, // texasr |
| | 955 | |
| | 956 | else => {}, |
| | 957 | } else switch (register_num) { |
| | 958 | 65 => return @ptrCast(&ctx.lr), // fpscr (SVR4 / EABI), or lr if you ask LLVM |
| | 959 | 108 => return @ptrCast(&ctx.lr), |
| | 960 | |
| | 961 | 64 => return error.UnsupportedRegister, // cr |
| | 962 | 66 => return error.UnsupportedRegister, // msr (SVR4 / EABI), or ctr if you ask LLVM |
| | 963 | 68...75 => return error.UnsupportedRegister, // cr0 - cr7 if you ask LLVM |
| | 964 | 76 => return error.UnsupportedRegister, // xer if you ask LLVM |
| | 965 | 99 => return error.UnsupportedRegister, // acc |
| | 966 | 100 => return error.UnsupportedRegister, // mq |
| | 967 | 101 => return error.UnsupportedRegister, // xer |
| | 968 | 102...107 => return error.UnsupportedRegister, // SPRs |
| | 969 | 109 => return error.UnsupportedRegister, // ctr |
| | 970 | 110...111 => return error.UnsupportedRegister, // SPRs |
| | 971 | 112 => return error.UnsupportedRegister, // spefscr |
| | 972 | 113...1123 => return error.UnsupportedRegister, // SPRs |
| | 973 | 1124...1155 => return error.UnsupportedRegister, // SPE v0 - v31 |
| | 974 | 1200...1231 => return error.UnsupportedRegister, // SPE upper r0 - r31 |
| | 975 | 3072...4095 => return error.UnsupportedRegister, // DCRs |
| | 976 | 4096...5120 => return error.UnsupportedRegister, // PMRs |
| | 977 | |
| | 978 | else => {}, |
| | 979 | } |
| | 980 | |
| | 981 | switch (register_num) { |
| | 982 | 0...31 => return @ptrCast(&ctx.r[register_num]), |
| | 983 | 67 => return @ptrCast(&ctx.pc), |
| | 984 | |
| | 985 | 32...63 => return error.UnsupportedRegister, // f0 - f31 |
| | 986 | |
| | 987 | else => return error.InvalidRegister, |
| | 988 | } |
| | 989 | } |
| | 990 | }; |
| | 991 | |
| | 992 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| | 993 | const Riscv = extern struct { |
| | 994 | /// The numbered general-purpose registers r0 - r31. r0 must be zero. |
| | 995 | r: [32]Gpr, |
| | 996 | pc: Gpr, |
| | 997 | |
| | 998 | pub const Gpr = if (builtin.target.cpu.arch.isRiscv64()) u64 else u32; |
| 684 | | 999 | |
| 685 | pub inline fn current() Riscv { | 1000 | pub inline fn current() Riscv { |
| 686 | var ctx: Riscv = undefined; | 1001 | var ctx: Riscv = undefined; |
| 687 | asm volatile (if (@sizeOf(usize) == 8) | 1002 | asm volatile (if (Gpr == u64) |
| 688 | \\ sd zero, 0(t0) | 1003 | \\ sd zero, 0(t0) |
| 689 | \\ sd ra, 8(t0) | 1004 | \\ sd ra, 8(t0) |
| 690 | \\ sd sp, 16(t0) | 1005 | \\ sd sp, 16(t0) |
| ... | @@ -767,7 +1082,13 @@ pub const Riscv = extern struct { | ... | @@ -767,7 +1082,13 @@ pub const Riscv = extern struct { |
| 767 | pub fn dwarfRegisterBytes(ctx: *Riscv, register_num: u16) DwarfRegisterError![]u8 { | 1082 | pub fn dwarfRegisterBytes(ctx: *Riscv, register_num: u16) DwarfRegisterError![]u8 { |
| 768 | switch (register_num) { | 1083 | switch (register_num) { |
| 769 | 0...31 => return @ptrCast(&ctx.r[register_num]), | 1084 | 0...31 => return @ptrCast(&ctx.r[register_num]), |
| 770 | 32 => return @ptrCast(&ctx.pc), | 1085 | 65 => return @ptrCast(&ctx.pc), |
| | 1086 | |
| | 1087 | 32...63 => return error.UnsupportedRegister, // f0 - f31 |
| | 1088 | 64 => return error.UnsupportedRegister, // Alternate Frame Return Column |
| | 1089 | 96...127 => return error.UnsupportedRegister, // v0 - v31 |
| | 1090 | 3072...4095 => return error.UnsupportedRegister, // Custom extensions |
| | 1091 | 4096...8191 => return error.UnsupportedRegister, // CSRs |
| 771 | | 1092 | |
| 772 | else => return error.InvalidRegister, | 1093 | else => return error.InvalidRegister, |
| 773 | } | 1094 | } |
| ... | @@ -775,11 +1096,9 @@ pub const Riscv = extern struct { | ... | @@ -775,11 +1096,9 @@ pub const Riscv = extern struct { |
| 775 | }; | 1096 | }; |
| 776 | | 1097 | |
| 777 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. | 1098 | /// This is an `extern struct` so that inline assembly in `current` can use field offsets. |
| 778 | pub const S390x = extern struct { | 1099 | const S390x = extern struct { |
| 779 | /// The numbered general-purpose registers r0 - r15. | 1100 | /// The numbered general-purpose registers r0 - r15. |
| 780 | r: [16]u64, | 1101 | r: [16]u64, |
| 781 | /// The numbered floating-point registers f0 - f15. Yes, really - they can be used in DWARF CFI. | | |
| 782 | f: [16]f64, | | |
| 783 | /// The program counter. | 1102 | /// The program counter. |
| 784 | psw: extern struct { | 1103 | psw: extern struct { |
| 785 | mask: u64, | 1104 | mask: u64, |
| ... | @@ -790,26 +1109,10 @@ pub const S390x = extern struct { | ... | @@ -790,26 +1109,10 @@ pub const S390x = extern struct { |
| 790 | var ctx: S390x = undefined; | 1109 | var ctx: S390x = undefined; |
| 791 | asm volatile ( | 1110 | asm volatile ( |
| 792 | \\ stmg %%r0, %%r15, 0(%%r2) | 1111 | \\ stmg %%r0, %%r15, 0(%%r2) |
| 793 | \\ std %%f0, 128(%%r2) | | |
| 794 | \\ std %%f1, 136(%%r2) | | |
| 795 | \\ std %%f2, 144(%%r2) | | |
| 796 | \\ std %%f3, 152(%%r2) | | |
| 797 | \\ std %%f4, 160(%%r2) | | |
| 798 | \\ std %%f5, 168(%%r2) | | |
| 799 | \\ std %%f6, 176(%%r2) | | |
| 800 | \\ std %%f7, 184(%%r2) | | |
| 801 | \\ std %%f8, 192(%%r2) | | |
| 802 | \\ std %%f9, 200(%%r2) | | |
| 803 | \\ std %%f10, 208(%%r2) | | |
| 804 | \\ std %%f11, 216(%%r2) | | |
| 805 | \\ std %%f12, 224(%%r2) | | |
| 806 | \\ std %%f13, 232(%%r2) | | |
| 807 | \\ std %%f14, 240(%%r2) | | |
| 808 | \\ std %%f15, 248(%%r2) | | |
| 809 | \\ epsw %%r0, %%r1 | 1112 | \\ epsw %%r0, %%r1 |
| 810 | \\ stm %%r0, %%r1, 256(%%r2) | 1113 | \\ stm %%r0, %%r1, 128(%%r2) |
| 811 | \\ larl %%r0, . | 1114 | \\ larl %%r0, . |
| 812 | \\ stg %%r0, 264(%%r2) | 1115 | \\ stg %%r0, 136(%%r2) |
| 813 | \\ lg %%r0, 0(%%r2) | 1116 | \\ lg %%r0, 0(%%r2) |
| 814 | \\ lg %%r1, 8(%%r2) | 1117 | \\ lg %%r1, 8(%%r2) |
| 815 | : | 1118 | : |
| ... | @@ -821,27 +1124,13 @@ pub const S390x = extern struct { | ... | @@ -821,27 +1124,13 @@ pub const S390x = extern struct { |
| 821 | pub fn dwarfRegisterBytes(ctx: *S390x, register_num: u16) DwarfRegisterError![]u8 { | 1124 | pub fn dwarfRegisterBytes(ctx: *S390x, register_num: u16) DwarfRegisterError![]u8 { |
| 822 | switch (register_num) { | 1125 | switch (register_num) { |
| 823 | 0...15 => return @ptrCast(&ctx.r[register_num]), | 1126 | 0...15 => return @ptrCast(&ctx.r[register_num]), |
| 824 | // Why??? | | |
| 825 | 16 => return @ptrCast(&ctx.f[0]), | | |
| 826 | 17 => return @ptrCast(&ctx.f[2]), | | |
| 827 | 18 => return @ptrCast(&ctx.f[4]), | | |
| 828 | 19 => return @ptrCast(&ctx.f[6]), | | |
| 829 | 20 => return @ptrCast(&ctx.f[1]), | | |
| 830 | 21 => return @ptrCast(&ctx.f[3]), | | |
| 831 | 22 => return @ptrCast(&ctx.f[5]), | | |
| 832 | 23 => return @ptrCast(&ctx.f[7]), | | |
| 833 | 24 => return @ptrCast(&ctx.f[8]), | | |
| 834 | 25 => return @ptrCast(&ctx.f[10]), | | |
| 835 | 26 => return @ptrCast(&ctx.f[12]), | | |
| 836 | 27 => return @ptrCast(&ctx.f[14]), | | |
| 837 | 28 => return @ptrCast(&ctx.f[9]), | | |
| 838 | 29 => return @ptrCast(&ctx.f[11]), | | |
| 839 | 30 => return @ptrCast(&ctx.f[13]), | | |
| 840 | 31 => return @ptrCast(&ctx.f[15]), | | |
| 841 | 64 => return @ptrCast(&ctx.psw.mask), | 1127 | 64 => return @ptrCast(&ctx.psw.mask), |
| 842 | 65 => return @ptrCast(&ctx.psw.addr), | 1128 | 65 => return @ptrCast(&ctx.psw.addr), |
| 843 | | 1129 | |
| | 1130 | 16...31 => return error.UnsupportedRegister, // f0 - f15 |
| | 1131 | 32...47 => return error.UnsupportedRegister, // cr0 - cr15 |
| 844 | 48...63 => return error.UnsupportedRegister, // a0 - a15 | 1132 | 48...63 => return error.UnsupportedRegister, // a0 - a15 |
| | 1133 | 66...67 => return error.UnsupportedRegister, // z/OS stuff??? |
| 845 | 68...83 => return error.UnsupportedRegister, // v16 - v31 | 1134 | 68...83 => return error.UnsupportedRegister, // v16 - v31 |
| 846 | | 1135 | |
| 847 | else => return error.InvalidRegister, | 1136 | else => return error.InvalidRegister, |