| ... | ... | @@ -216,7 +216,7 @@ pub const Instruction = union(enum) { |
| 216 | 216 | reserved: u8 = 0b00000000, |
| 217 | 217 | rs2: u5, |
| 218 | 218 | }, |
| 219 | | format_3b: packed struct { |
| 219 | format_3b: struct { |
| 220 | 220 | op: u2, |
| 221 | 221 | rd: u5, |
| 222 | 222 | op3: u6, |
| ... | ... | @@ -233,7 +233,7 @@ pub const Instruction = union(enum) { |
| 233 | 233 | reserved2: u8 = 0b00000000, |
| 234 | 234 | rs2: u5, |
| 235 | 235 | }, |
| 236 | | format_3d: packed struct { |
| 236 | format_3d: struct { |
| 237 | 237 | op: u2, |
| 238 | 238 | reserved: u5 = 0b00000, |
| 239 | 239 | op3: u6, |
| ... | ... | @@ -251,7 +251,7 @@ pub const Instruction = union(enum) { |
| 251 | 251 | reserved: u5 = 0b00000, |
| 252 | 252 | rs2: u5, |
| 253 | 253 | }, |
| 254 | | format_3f: packed struct { |
| 254 | format_3f: struct { |
| 255 | 255 | op: u2, |
| 256 | 256 | rd: u5, |
| 257 | 257 | op3: u6, |
| ... | ... | @@ -270,7 +270,7 @@ pub const Instruction = union(enum) { |
| 270 | 270 | rs2: u5, |
| 271 | 271 | }, |
| 272 | 272 | format_3h: packed struct { |
| 273 | | op: u2, |
| 273 | op: u2 = 0b10, |
| 274 | 274 | fixed1: u5 = 0b00000, |
| 275 | 275 | op3: u6 = 0b101000, |
| 276 | 276 | fixed2: u5 = 0b01111, |
| ... | ... | @@ -336,8 +336,9 @@ pub const Instruction = union(enum) { |
| 336 | 336 | op: u2, |
| 337 | 337 | fixed: u3 = 0b000, |
| 338 | 338 | cc1: u1, |
| 339 | | cc0: i1, |
| 339 | cc0: u1, |
| 340 | 340 | op3: u6, |
| 341 | rs1: u5, |
| 341 | 342 | opf: u9, |
| 342 | 343 | rs2: u5, |
| 343 | 344 | }, |
| ... | ... | @@ -381,7 +382,7 @@ pub const Instruction = union(enum) { |
| 381 | 382 | reserved: u6 = 0b000000, |
| 382 | 383 | rs2: u5, |
| 383 | 384 | }, |
| 384 | | format_4b: packed struct { |
| 385 | format_4b: struct { |
| 385 | 386 | op: u2 = 0b10, |
| 386 | 387 | rd: u5, |
| 387 | 388 | op3: u6, |
| ... | ... | @@ -403,7 +404,7 @@ pub const Instruction = union(enum) { |
| 403 | 404 | reserved: u6 = 0b000000, |
| 404 | 405 | rs2: u5, |
| 405 | 406 | }, |
| 406 | | format_4d: packed struct { |
| 407 | format_4d: struct { |
| 407 | 408 | op: u2 = 0b10, |
| 408 | 409 | rd: u5, |
| 409 | 410 | op3: u6, |
| ... | ... | @@ -486,8 +487,8 @@ pub const Instruction = union(enum) { |
| 486 | 487 | }; |
| 487 | 488 | |
| 488 | 489 | pub const ShiftWidth = enum(u1) { |
| 489 | | Shift32, |
| 490 | | Shift64, |
| 490 | shift32, |
| 491 | shift64, |
| 491 | 492 | }; |
| 492 | 493 | |
| 493 | 494 | pub const MemOrderingConstraint = packed struct { |
| ... | ... | @@ -509,7 +510,40 @@ pub const Instruction = union(enum) { |
| 509 | 510 | pub const Condition = u4; |
| 510 | 511 | |
| 511 | 512 | pub fn toU32(self: Instruction) u32 { |
| 512 | | return @bitCast(u32, self); |
| 513 | // TODO: Remove this once packed structs work. |
| 514 | return switch (self) { |
| 515 | .format_1 => |v| @bitCast(u32, v), |
| 516 | .format_2a => |v| @bitCast(u32, v), |
| 517 | .format_2b => |v| @bitCast(u32, v), |
| 518 | .format_2c => |v| @bitCast(u32, v), |
| 519 | .format_2d => |v| @bitCast(u32, v), |
| 520 | .format_3a => |v| @bitCast(u32, v), |
| 521 | .format_3b => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.rs1) << 14) | (@as(u32, v.i) << 13) | @as(u32, v.simm13), |
| 522 | .format_3c => |v| @bitCast(u32, v), |
| 523 | .format_3d => |v| (@as(u32, v.op) << 30) | (@as(u32, v.reserved) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.rs1) << 14) | (@as(u32, v.i) << 13) | @as(u32, v.simm13), |
| 524 | .format_3e => |v| @bitCast(u32, v), |
| 525 | .format_3f => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.rs1) << 14) | (@as(u32, v.i) << 13) | (@as(u32, v.rcond) << 10) | @as(u32, v.simm10), |
| 526 | .format_3g => |v| @bitCast(u32, v), |
| 527 | .format_3h => |v| @bitCast(u32, v), |
| 528 | .format_3i => |v| @bitCast(u32, v), |
| 529 | .format_3j => |v| @bitCast(u32, v), |
| 530 | .format_3k => |v| @bitCast(u32, v), |
| 531 | .format_3l => |v| @bitCast(u32, v), |
| 532 | .format_3m => |v| @bitCast(u32, v), |
| 533 | .format_3n => |v| @bitCast(u32, v), |
| 534 | .format_3o => |v| @bitCast(u32, v), |
| 535 | .format_3p => |v| @bitCast(u32, v), |
| 536 | .format_3q => |v| @bitCast(u32, v), |
| 537 | .format_3r => |v| @bitCast(u32, v), |
| 538 | .format_3s => |v| @bitCast(u32, v), |
| 539 | .format_4a => |v| @bitCast(u32, v), |
| 540 | .format_4b => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.rs1) << 14) | (@as(u32, v.i) << 13) | (@as(u32, v.cc1) << 12) | (@as(u32, v.cc0) << 11) | @as(u32, v.simm11), |
| 541 | .format_4c => |v| @bitCast(u32, v), |
| 542 | .format_4d => |v| (@as(u32, v.op) << 30) | (@as(u32, v.rd) << 25) | (@as(u32, v.op3) << 19) | (@as(u32, v.cc2) << 18) | (@as(u32, v.cond) << 14) | (@as(u32, v.i) << 13) | (@as(u32, v.cc1) << 12) | (@as(u32, v.cc0) << 11) | @as(u32, v.simm11), |
| 543 | .format_4e => |v| @bitCast(u32, v), |
| 544 | .format_4f => |v| @bitCast(u32, v), |
| 545 | .format_4g => |v| @bitCast(u32, v), |
| 546 | }; |
| 513 | 547 | } |
| 514 | 548 | |
| 515 | 549 | fn format1(disp: i32) Instruction { |
| ... | ... | @@ -527,12 +561,12 @@ pub const Instruction = union(enum) { |
| 527 | 561 | }; |
| 528 | 562 | } |
| 529 | 563 | |
| 530 | | fn format2a(op2: u3, rd: Register, imm: i22) Instruction { |
| 564 | fn format2a(op2: u3, rd: Register, imm: u22) Instruction { |
| 531 | 565 | return Instruction{ |
| 532 | 566 | .format_2a = .{ |
| 533 | 567 | .rd = rd.enc(), |
| 534 | 568 | .op2 = op2, |
| 535 | | .imm22 = @bitCast(u22, imm), |
| 569 | .imm22 = imm, |
| 536 | 570 | }, |
| 537 | 571 | }; |
| 538 | 572 | } |
| ... | ... | @@ -580,17 +614,18 @@ pub const Instruction = union(enum) { |
| 580 | 614 | } |
| 581 | 615 | |
| 582 | 616 | fn format2d(op2: u3, rcond: RCondition, annul: bool, pt: bool, rs1: Register, disp: i18) Instruction { |
| 583 | | const udisp = @truncate(u16, @bitCast(u18, disp) >> 2); |
| 617 | const udisp = @bitCast(u18, disp); |
| 584 | 618 | |
| 585 | 619 | // In SPARC, branch target needs to be aligned to 4 bytes. |
| 586 | 620 | assert(udisp % 4 == 0); |
| 587 | 621 | |
| 588 | 622 | // Discard the last two bits since those are implicitly zero, |
| 589 | 623 | // and split it into low and high parts. |
| 590 | | const udisp_hi = @truncate(u2, (udisp & 0b1100_0000_0000_0000) >> 14); |
| 591 | | const udisp_lo = @truncate(u14, udisp & 0b0011_1111_1111_1111); |
| 624 | const udisp_truncated = @truncate(u16, udisp >> 2); |
| 625 | const udisp_hi = @truncate(u2, (udisp_truncated & 0b1100_0000_0000_0000) >> 14); |
| 626 | const udisp_lo = @truncate(u14, udisp_truncated & 0b0011_1111_1111_1111); |
| 592 | 627 | return Instruction{ |
| 593 | | .format_2a = .{ |
| 628 | .format_2d = .{ |
| 594 | 629 | .a = @boolToInt(annul), |
| 595 | 630 | .rcond = @enumToInt(rcond), |
| 596 | 631 | .op2 = op2, |
| ... | ... | @@ -602,9 +637,10 @@ pub const Instruction = union(enum) { |
| 602 | 637 | }; |
| 603 | 638 | } |
| 604 | 639 | |
| 605 | | fn format3a(op3: u6, rs1: Register, rs2: Register, rd: Register) Instruction { |
| 640 | fn format3a(op: u2, op3: u6, rs1: Register, rs2: Register, rd: Register) Instruction { |
| 606 | 641 | return Instruction{ |
| 607 | 642 | .format_3a = .{ |
| 643 | .op = op, |
| 608 | 644 | .rd = rd.enc(), |
| 609 | 645 | .op3 = op3, |
| 610 | 646 | .rs1 = rs1.enc(), |
| ... | ... | @@ -612,9 +648,10 @@ pub const Instruction = union(enum) { |
| 612 | 648 | }, |
| 613 | 649 | }; |
| 614 | 650 | } |
| 615 | | fn format3b(op3: u6, rs1: Register, imm: i13, rd: Register) Instruction { |
| 651 | fn format3b(op: u2, op3: u6, rs1: Register, imm: i13, rd: Register) Instruction { |
| 616 | 652 | return Instruction{ |
| 617 | 653 | .format_3b = .{ |
| 654 | .op = op, |
| 618 | 655 | .rd = rd.enc(), |
| 619 | 656 | .op3 = op3, |
| 620 | 657 | .rs1 = rs1.enc(), |
| ... | ... | @@ -622,27 +659,30 @@ pub const Instruction = union(enum) { |
| 622 | 659 | }, |
| 623 | 660 | }; |
| 624 | 661 | } |
| 625 | | fn format3c(op3: u6, rs1: Register, rs2: Register) Instruction { |
| 662 | fn format3c(op: u2, op3: u6, rs1: Register, rs2: Register) Instruction { |
| 626 | 663 | return Instruction{ |
| 627 | 664 | .format_3c = .{ |
| 665 | .op = op, |
| 628 | 666 | .op3 = op3, |
| 629 | 667 | .rs1 = rs1.enc(), |
| 630 | 668 | .rs2 = rs2.enc(), |
| 631 | 669 | }, |
| 632 | 670 | }; |
| 633 | 671 | } |
| 634 | | fn format3d(op3: u6, rs1: Register, imm: i13) Instruction { |
| 672 | fn format3d(op: u2, op3: u6, rs1: Register, imm: i13) Instruction { |
| 635 | 673 | return Instruction{ |
| 636 | 674 | .format_3d = .{ |
| 675 | .op = op, |
| 637 | 676 | .op3 = op3, |
| 638 | 677 | .rs1 = rs1.enc(), |
| 639 | 678 | .simm13 = @bitCast(u13, imm), |
| 640 | 679 | }, |
| 641 | 680 | }; |
| 642 | 681 | } |
| 643 | | fn format3e(op3: u6, rcond: RCondition, rs1: Register, rs2: Register, rd: Register) Instruction { |
| 682 | fn format3e(op: u2, op3: u6, rcond: RCondition, rs1: Register, rs2: Register, rd: Register) Instruction { |
| 644 | 683 | return Instruction{ |
| 645 | 684 | .format_3e = .{ |
| 685 | .op = op, |
| 646 | 686 | .rd = rd.enc(), |
| 647 | 687 | .op3 = op3, |
| 648 | 688 | .rs1 = rs1.enc(), |
| ... | ... | @@ -651,9 +691,10 @@ pub const Instruction = union(enum) { |
| 651 | 691 | }, |
| 652 | 692 | }; |
| 653 | 693 | } |
| 654 | | fn format3f(op3: u6, rcond: RCondition, rs1: Register, imm: i10, rd: Register) Instruction { |
| 694 | fn format3f(op: u2, op3: u6, rcond: RCondition, rs1: Register, imm: i10, rd: Register) Instruction { |
| 655 | 695 | return Instruction{ |
| 656 | 696 | .format_3f = .{ |
| 697 | .op = op, |
| 657 | 698 | .rd = rd.enc(), |
| 658 | 699 | .op3 = op3, |
| 659 | 700 | .rs1 = rs1.enc(), |
| ... | ... | @@ -662,9 +703,10 @@ pub const Instruction = union(enum) { |
| 662 | 703 | }, |
| 663 | 704 | }; |
| 664 | 705 | } |
| 665 | | fn format3g(op3: u6, rs1: Register, rs2: Register, rd: Register) Instruction { |
| 706 | fn format3g(op: u2, op3: u6, rs1: Register, rs2: Register, rd: Register) Instruction { |
| 666 | 707 | return Instruction{ |
| 667 | 708 | .format_3g = .{ |
| 709 | .op = op, |
| 668 | 710 | .rd = rd.enc(), |
| 669 | 711 | .op3 = op3, |
| 670 | 712 | .rs1 = rs1.enc(), |
| ... | ... | @@ -680,9 +722,10 @@ pub const Instruction = union(enum) { |
| 680 | 722 | }, |
| 681 | 723 | }; |
| 682 | 724 | } |
| 683 | | fn format3i(op3: u6, rs1: Register, rs2: Register, rd: Register, asi: ASI) Instruction { |
| 725 | fn format3i(op: u2, op3: u6, rs1: Register, rs2: Register, rd: Register, asi: ASI) Instruction { |
| 684 | 726 | return Instruction{ |
| 685 | 727 | .format_3i = .{ |
| 728 | .op = op, |
| 686 | 729 | .rd = rd.enc(), |
| 687 | 730 | .op3 = op3, |
| 688 | 731 | .rs1 = rs1.enc(), |
| ... | ... | @@ -691,18 +734,20 @@ pub const Instruction = union(enum) { |
| 691 | 734 | }, |
| 692 | 735 | }; |
| 693 | 736 | } |
| 694 | | fn format3j(op3: u6, impl_dep1: u5, impl_dep2: u19) Instruction { |
| 737 | fn format3j(op: u2, op3: u6, impl_dep1: u5, impl_dep2: u19) Instruction { |
| 695 | 738 | return Instruction{ |
| 696 | 739 | .format_3j = .{ |
| 740 | .op = op, |
| 697 | 741 | .impl_dep1 = impl_dep1, |
| 698 | 742 | .op3 = op3, |
| 699 | 743 | .impl_dep2 = impl_dep2, |
| 700 | 744 | }, |
| 701 | 745 | }; |
| 702 | 746 | } |
| 703 | | fn format3k(op3: u6, sw: ShiftWidth, rs1: Register, rs2: Register, rd: Register) Instruction { |
| 747 | fn format3k(op: u2, op3: u6, sw: ShiftWidth, rs1: Register, rs2: Register, rd: Register) Instruction { |
| 704 | 748 | return Instruction{ |
| 705 | 749 | .format_3k = .{ |
| 750 | .op = op, |
| 706 | 751 | .rd = rd.enc(), |
| 707 | 752 | .op3 = op3, |
| 708 | 753 | .rs1 = rs1.enc(), |
| ... | ... | @@ -711,29 +756,32 @@ pub const Instruction = union(enum) { |
| 711 | 756 | }, |
| 712 | 757 | }; |
| 713 | 758 | } |
| 714 | | fn format3l(op3: u6, rs1: Register, shift_count: u5, rd: Register) Instruction { |
| 759 | fn format3l(op: u2, op3: u6, rs1: Register, shift_count: u5, rd: Register) Instruction { |
| 715 | 760 | return Instruction{ |
| 716 | 761 | .format_3l = .{ |
| 762 | .op = op, |
| 717 | 763 | .rd = rd.enc(), |
| 718 | 764 | .op3 = op3, |
| 719 | 765 | .rs1 = rs1.enc(), |
| 720 | | .shift_count = shift_count, |
| 766 | .shcnt32 = shift_count, |
| 721 | 767 | }, |
| 722 | 768 | }; |
| 723 | 769 | } |
| 724 | | fn format3m(op3: u6, rs1: Register, shift_count: u6, rd: Register) Instruction { |
| 770 | fn format3m(op: u2, op3: u6, rs1: Register, shift_count: u6, rd: Register) Instruction { |
| 725 | 771 | return Instruction{ |
| 726 | 772 | .format_3m = .{ |
| 773 | .op = op, |
| 727 | 774 | .rd = rd.enc(), |
| 728 | 775 | .op3 = op3, |
| 729 | 776 | .rs1 = rs1.enc(), |
| 730 | | .shift_count = shift_count, |
| 777 | .shcnt64 = shift_count, |
| 731 | 778 | }, |
| 732 | 779 | }; |
| 733 | 780 | } |
| 734 | | fn format3n(op3: u6, opf: u9, rs2: Register, rd: Register) Instruction { |
| 781 | fn format3n(op: u2, op3: u6, opf: u9, rs2: Register, rd: Register) Instruction { |
| 735 | 782 | return Instruction{ |
| 736 | 783 | .format_3n = .{ |
| 784 | .op = op, |
| 737 | 785 | .rd = rd.enc(), |
| 738 | 786 | .op3 = op3, |
| 739 | 787 | .opf = opf, |
| ... | ... | @@ -741,11 +789,12 @@ pub const Instruction = union(enum) { |
| 741 | 789 | }, |
| 742 | 790 | }; |
| 743 | 791 | } |
| 744 | | fn format3o(op3: u6, opf: u9, ccr: CCR, rs1: Register, rs2: Register) Instruction { |
| 792 | fn format3o(op: u2, op3: u6, opf: u9, ccr: CCR, rs1: Register, rs2: Register) Instruction { |
| 745 | 793 | const ccr_cc1 = @truncate(u1, @enumToInt(ccr) >> 1); |
| 746 | 794 | const ccr_cc0 = @truncate(u1, @enumToInt(ccr)); |
| 747 | 795 | return Instruction{ |
| 748 | 796 | .format_3o = .{ |
| 797 | .op = op, |
| 749 | 798 | .cc1 = ccr_cc1, |
| 750 | 799 | .cc0 = ccr_cc0, |
| 751 | 800 | .op3 = op3, |
| ... | ... | @@ -755,9 +804,10 @@ pub const Instruction = union(enum) { |
| 755 | 804 | }, |
| 756 | 805 | }; |
| 757 | 806 | } |
| 758 | | fn format3p(op3: u6, opf: u9, rs1: Register, rs2: Register, rd: Register) Instruction { |
| 807 | fn format3p(op: u2, op3: u6, opf: u9, rs1: Register, rs2: Register, rd: Register) Instruction { |
| 759 | 808 | return Instruction{ |
| 760 | 809 | .format_3p = .{ |
| 810 | .op = op, |
| 761 | 811 | .rd = rd.enc(), |
| 762 | 812 | .op3 = op3, |
| 763 | 813 | .rs1 = rs1.enc(), |
| ... | ... | @@ -766,26 +816,29 @@ pub const Instruction = union(enum) { |
| 766 | 816 | }, |
| 767 | 817 | }; |
| 768 | 818 | } |
| 769 | | fn format3q(op3: u6, rs1: Register, rd: Register) Instruction { |
| 819 | fn format3q(op: u2, op3: u6, rs1: Register, rd: Register) Instruction { |
| 770 | 820 | return Instruction{ |
| 771 | 821 | .format_3q = .{ |
| 822 | .op = op, |
| 772 | 823 | .rd = rd.enc(), |
| 773 | 824 | .op3 = op3, |
| 774 | 825 | .rs1 = rs1.enc(), |
| 775 | 826 | }, |
| 776 | 827 | }; |
| 777 | 828 | } |
| 778 | | fn format3r(op3: u6, fcn: u5) Instruction { |
| 829 | fn format3r(op: u2, op3: u6, fcn: u5) Instruction { |
| 779 | 830 | return Instruction{ |
| 780 | 831 | .format_3r = .{ |
| 832 | .op = op, |
| 781 | 833 | .fcn = fcn, |
| 782 | 834 | .op3 = op3, |
| 783 | 835 | }, |
| 784 | 836 | }; |
| 785 | 837 | } |
| 786 | | fn format3s(op3: u6, rd: Register) Instruction { |
| 838 | fn format3s(op: u2, op3: u6, rd: Register) Instruction { |
| 787 | 839 | return Instruction{ |
| 788 | 840 | .format_3s = .{ |
| 841 | .op = op, |
| 789 | 842 | .rd = rd.enc(), |
| 790 | 843 | .op3 = op3, |
| 791 | 844 | }, |
| ... | ... | @@ -796,7 +849,7 @@ pub const Instruction = union(enum) { |
| 796 | 849 | const ccr_cc1 = @truncate(u1, @enumToInt(ccr) >> 1); |
| 797 | 850 | const ccr_cc0 = @truncate(u1, @enumToInt(ccr)); |
| 798 | 851 | return Instruction{ |
| 799 | | .format4a = .{ |
| 852 | .format_4a = .{ |
| 800 | 853 | .rd = rd.enc(), |
| 801 | 854 | .op3 = op3, |
| 802 | 855 | .rs1 = rs1.enc(), |
| ... | ... | @@ -811,7 +864,7 @@ pub const Instruction = union(enum) { |
| 811 | 864 | const ccr_cc1 = @truncate(u1, @enumToInt(ccr) >> 1); |
| 812 | 865 | const ccr_cc0 = @truncate(u1, @enumToInt(ccr)); |
| 813 | 866 | return Instruction{ |
| 814 | | .format4b = .{ |
| 867 | .format_4b = .{ |
| 815 | 868 | .rd = rd.enc(), |
| 816 | 869 | .op3 = op3, |
| 817 | 870 | .rs1 = rs1.enc(), |
| ... | ... | @@ -827,7 +880,7 @@ pub const Instruction = union(enum) { |
| 827 | 880 | const ccr_cc1 = @truncate(u1, @enumToInt(ccr) >> 1); |
| 828 | 881 | const ccr_cc0 = @truncate(u1, @enumToInt(ccr)); |
| 829 | 882 | return Instruction{ |
| 830 | | .format4c = .{ |
| 883 | .format_4c = .{ |
| 831 | 884 | .rd = rd.enc(), |
| 832 | 885 | .op3 = op3, |
| 833 | 886 | .cc2 = ccr_cc2, |
| ... | ... | @@ -844,7 +897,7 @@ pub const Instruction = union(enum) { |
| 844 | 897 | const ccr_cc1 = @truncate(u1, @enumToInt(ccr) >> 1); |
| 845 | 898 | const ccr_cc0 = @truncate(u1, @enumToInt(ccr)); |
| 846 | 899 | return Instruction{ |
| 847 | | .format4d = .{ |
| 900 | .format_4d = .{ |
| 848 | 901 | .rd = rd.enc(), |
| 849 | 902 | .op3 = op3, |
| 850 | 903 | .cc2 = ccr_cc2, |
| ... | ... | @@ -860,7 +913,7 @@ pub const Instruction = union(enum) { |
| 860 | 913 | const ccr_cc1 = @truncate(u1, @enumToInt(ccr) >> 1); |
| 861 | 914 | const ccr_cc0 = @truncate(u1, @enumToInt(ccr)); |
| 862 | 915 | return Instruction{ |
| 863 | | .format4e = .{ |
| 916 | .format_4e = .{ |
| 864 | 917 | .rd = rd.enc(), |
| 865 | 918 | .op3 = op3, |
| 866 | 919 | .rs1 = rs1.enc(), |
| ... | ... | @@ -880,7 +933,7 @@ pub const Instruction = union(enum) { |
| 880 | 933 | rd: Register, |
| 881 | 934 | ) Instruction { |
| 882 | 935 | return Instruction{ |
| 883 | | .format4f = .{ |
| 936 | .format_4f = .{ |
| 884 | 937 | .rd = rd.enc(), |
| 885 | 938 | .op3 = op3, |
| 886 | 939 | .rs1 = rs1.enc(), |
| ... | ... | @@ -893,7 +946,7 @@ pub const Instruction = union(enum) { |
| 893 | 946 | |
| 894 | 947 | fn format4g(op3: u6, opf_low: u6, opf_cc: u3, cond: Condition, rs2: Register, rd: Register) Instruction { |
| 895 | 948 | return Instruction{ |
| 896 | | .format4g = .{ |
| 949 | .format_4g = .{ |
| 897 | 950 | .rd = rd.enc(), |
| 898 | 951 | .op3 = op3, |
| 899 | 952 | .cond = cond, |
| ... | ... | @@ -904,3 +957,145 @@ pub const Instruction = union(enum) { |
| 904 | 957 | }; |
| 905 | 958 | } |
| 906 | 959 | }; |
| 960 | |
| 961 | test "Serialize formats" { |
| 962 | const Testcase = struct { |
| 963 | inst: Instruction, |
| 964 | expected: u32, |
| 965 | }; |
| 966 | |
| 967 | // Note that the testcases might or might not be a valid instruction |
| 968 | // This is mostly just to check the behavior of the format packed structs |
| 969 | // since currently stage1 doesn't properly implement it in all cases |
| 970 | const testcases = [_]Testcase{ |
| 971 | .{ |
| 972 | .inst = Instruction.format1(4), |
| 973 | .expected = 0b01_000000000000000000000000000001, |
| 974 | }, |
| 975 | .{ |
| 976 | .inst = Instruction.format2a(4, .g0, 0), |
| 977 | .expected = 0b00_00000_100_0000000000000000000000, |
| 978 | }, |
| 979 | .{ |
| 980 | .inst = Instruction.format2b(6, 3, true, -4), |
| 981 | .expected = 0b00_1_0011_110_1111111111111111111111, |
| 982 | }, |
| 983 | .{ |
| 984 | .inst = Instruction.format2c(3, 0, false, true, .xcc, 8), |
| 985 | .expected = 0b00_0_0000_011_1_0_1_0000000000000000010, |
| 986 | }, |
| 987 | .{ |
| 988 | .inst = Instruction.format2d(7, .eq_zero, false, true, .o0, 20), |
| 989 | .expected = 0b00_0_0_001_111_00_1_01000_00000000000101, |
| 990 | }, |
| 991 | .{ |
| 992 | .inst = Instruction.format3a(3, 5, .g0, .o1, .l2), |
| 993 | .expected = 0b11_10010_000101_00000_0_00000000_01001, |
| 994 | }, |
| 995 | .{ |
| 996 | .inst = Instruction.format3b(3, 5, .g0, -1, .l2), |
| 997 | .expected = 0b11_10010_000101_00000_1_1111111111111, |
| 998 | }, |
| 999 | .{ |
| 1000 | .inst = Instruction.format3c(3, 5, .g0, .o1), |
| 1001 | .expected = 0b11_00000_000101_00000_0_00000000_01001, |
| 1002 | }, |
| 1003 | .{ |
| 1004 | .inst = Instruction.format3d(3, 5, .g0, 0), |
| 1005 | .expected = 0b11_00000_000101_00000_1_0000000000000, |
| 1006 | }, |
| 1007 | .{ |
| 1008 | .inst = Instruction.format3e(3, 5, .ne_zero, .g0, .o1, .l2), |
| 1009 | .expected = 0b11_10010_000101_00000_0_101_00000_01001, |
| 1010 | }, |
| 1011 | .{ |
| 1012 | .inst = Instruction.format3f(3, 5, .ne_zero, .g0, -1, .l2), |
| 1013 | .expected = 0b11_10010_000101_00000_1_101_1111111111, |
| 1014 | }, |
| 1015 | .{ |
| 1016 | .inst = Instruction.format3g(3, 5, .g0, .o1, .l2), |
| 1017 | .expected = 0b11_10010_000101_00000_1_00000000_01001, |
| 1018 | }, |
| 1019 | .{ |
| 1020 | .inst = Instruction.format3h(.{}, .{}), |
| 1021 | .expected = 0b10_00000_101000_01111_1_000000_000_0000, |
| 1022 | }, |
| 1023 | .{ |
| 1024 | .inst = Instruction.format3i(3, 5, .g0, .o1, .l2, .asi_primary_little), |
| 1025 | .expected = 0b11_10010_000101_00000_0_10001000_01001, |
| 1026 | }, |
| 1027 | .{ |
| 1028 | .inst = Instruction.format3j(3, 5, 31, 0), |
| 1029 | .expected = 0b11_11111_000101_0000000000000000000, |
| 1030 | }, |
| 1031 | .{ |
| 1032 | .inst = Instruction.format3k(3, 5, .shift32, .g0, .o1, .l2), |
| 1033 | .expected = 0b11_10010_000101_00000_0_0_0000000_01001, |
| 1034 | }, |
| 1035 | .{ |
| 1036 | .inst = Instruction.format3l(3, 5, .g0, 31, .l2), |
| 1037 | .expected = 0b11_10010_000101_00000_1_0_0000000_11111, |
| 1038 | }, |
| 1039 | .{ |
| 1040 | .inst = Instruction.format3m(3, 5, .g0, 63, .l2), |
| 1041 | .expected = 0b11_10010_000101_00000_1_1_000000_111111, |
| 1042 | }, |
| 1043 | .{ |
| 1044 | .inst = Instruction.format3n(3, 5, 0, .o1, .l2), |
| 1045 | .expected = 0b11_10010_000101_00000_000000000_01001, |
| 1046 | }, |
| 1047 | .{ |
| 1048 | .inst = Instruction.format3o(3, 5, 0, .xcc, .o1, .l2), |
| 1049 | .expected = 0b11_000_1_0_000101_01001_000000000_10010, |
| 1050 | }, |
| 1051 | .{ |
| 1052 | .inst = Instruction.format3p(3, 5, 0, .g0, .o1, .l2), |
| 1053 | .expected = 0b11_10010_000101_00000_000000000_01001, |
| 1054 | }, |
| 1055 | .{ |
| 1056 | .inst = Instruction.format3q(3, 5, .g0, .o1), |
| 1057 | .expected = 0b11_01001_000101_00000_00000000000000, |
| 1058 | }, |
| 1059 | .{ |
| 1060 | .inst = Instruction.format3r(3, 5, 4), |
| 1061 | .expected = 0b11_00100_000101_0000000000000000000, |
| 1062 | }, |
| 1063 | .{ |
| 1064 | .inst = Instruction.format3s(3, 5, .g0), |
| 1065 | .expected = 0b11_00000_000101_0000000000000000000, |
| 1066 | }, |
| 1067 | .{ |
| 1068 | .inst = Instruction.format4a(8, .xcc, .g0, .o1, .l2), |
| 1069 | .expected = 0b10_10010_001000_00000_0_1_0_000000_01001, |
| 1070 | }, |
| 1071 | .{ |
| 1072 | .inst = Instruction.format4b(8, .xcc, .g0, -1, .l2), |
| 1073 | .expected = 0b10_10010_001000_00000_1_1_0_11111111111, |
| 1074 | }, |
| 1075 | .{ |
| 1076 | .inst = Instruction.format4c(8, 0, .xcc, .g0, .o1), |
| 1077 | .expected = 0b10_01001_001000_1_0000_0_1_0_000000_00000, |
| 1078 | }, |
| 1079 | .{ |
| 1080 | .inst = Instruction.format4d(8, 0, .xcc, 0, .l2), |
| 1081 | .expected = 0b10_10010_001000_1_0000_1_1_0_00000000000 |
| 1082 | }, |
| 1083 | .{ |
| 1084 | .inst = Instruction.format4e(8, .xcc, .g0, .o1, 0), |
| 1085 | .expected = 0b10_01001_001000_00000_1_1_0_0000_0000000, |
| 1086 | }, |
| 1087 | .{ |
| 1088 | .inst = Instruction.format4f(8, 4, .eq_zero, .g0, .o1, .l2), |
| 1089 | .expected = 0b10_10010_001000_00000_0_001_00100_01001, |
| 1090 | }, |
| 1091 | .{ |
| 1092 | .inst = Instruction.format4g(8, 4, 2, 0, .o1, .l2), |
| 1093 | .expected = 0b10_10010_001000_0_0000_010_000100_01001, |
| 1094 | }, |
| 1095 | }; |
| 1096 | |
| 1097 | for (testcases) |case| { |
| 1098 | const actual = case.inst.toU32(); |
| 1099 | try testing.expectEqual(case.expected, actual); |
| 1100 | } |
| 1101 | } |