| ... | @@ -274,6 +274,16 @@ pub const Instruction = union(enum) { | ... | @@ -274,6 +274,16 @@ pub const Instruction = union(enum) { |
| 274 | opc: u2, | 274 | opc: u2, |
| 275 | sf: u1, | 275 | sf: u1, |
| 276 | }, | 276 | }, |
| | 277 | AddSubtractImmediate: packed struct { |
| | 278 | rd: u5, |
| | 279 | rn: u5, |
| | 280 | imm12: u12, |
| | 281 | sh: u1, |
| | 282 | fixed: u6 = 0b100010, |
| | 283 | s: u1, |
| | 284 | op: u1, |
| | 285 | sf: u1, |
| | 286 | }, |
| 277 | | 287 | |
| 278 | pub const Shift = struct { | 288 | pub const Shift = struct { |
| 279 | shift: Type = .lsl, | 289 | shift: Type = .lsl, |
| ... | @@ -304,6 +314,7 @@ pub const Instruction = union(enum) { | ... | @@ -304,6 +314,7 @@ pub const Instruction = union(enum) { |
| 304 | .UnconditionalBranchImmediate => |v| @bitCast(u32, v), | 314 | .UnconditionalBranchImmediate => |v| @bitCast(u32, v), |
| 305 | .NoOperation => |v| @bitCast(u32, v), | 315 | .NoOperation => |v| @bitCast(u32, v), |
| 306 | .LogicalShiftedRegister => |v| @bitCast(u32, v), | 316 | .LogicalShiftedRegister => |v| @bitCast(u32, v), |
| | 317 | .AddSubtractImmediate => |v| @bitCast(u32, v), |
| 307 | }; | 318 | }; |
| 308 | } | 319 | } |
| 309 | | 320 | |
| ... | @@ -671,6 +682,31 @@ pub const Instruction = union(enum) { | ... | @@ -671,6 +682,31 @@ pub const Instruction = union(enum) { |
| 671 | } | 682 | } |
| 672 | } | 683 | } |
| 673 | | 684 | |
| | 685 | fn addSubtractImmediate( |
| | 686 | op: u1, |
| | 687 | s: u1, |
| | 688 | rd: Register, |
| | 689 | rn: Register, |
| | 690 | imm12: u12, |
| | 691 | shift: bool, |
| | 692 | ) Instruction { |
| | 693 | return Instruction{ |
| | 694 | .AddSubtractImmediate = .{ |
| | 695 | .rd = rd.id(), |
| | 696 | .rn = rn.id(), |
| | 697 | .imm12 = imm12, |
| | 698 | .sh = @boolToInt(shift), |
| | 699 | .s = s, |
| | 700 | .op = op, |
| | 701 | .sf = switch (rd.size()) { |
| | 702 | 32 => 0b0, |
| | 703 | 64 => 0b1, |
| | 704 | else => unreachable, // unexpected register size |
| | 705 | }, |
| | 706 | }, |
| | 707 | }; |
| | 708 | } |
| | 709 | |
| 674 | // Helper functions for assembly syntax functions | 710 | // Helper functions for assembly syntax functions |
| 675 | | 711 | |
| 676 | // Move wide (immediate) | 712 | // Move wide (immediate) |
| ... | @@ -850,6 +886,24 @@ pub const Instruction = union(enum) { | ... | @@ -850,6 +886,24 @@ pub const Instruction = union(enum) { |
| 850 | pub fn bics(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction { | 886 | pub fn bics(rd: Register, rn: Register, rm: Register, shift: Shift) Instruction { |
| 851 | return logicalShiftedRegister(0b11, 0b1, shift, rd, rn, rm); | 887 | return logicalShiftedRegister(0b11, 0b1, shift, rd, rn, rm); |
| 852 | } | 888 | } |
| | 889 | |
| | 890 | // Add/subtract (immediate) |
| | 891 | |
| | 892 | pub fn add(rd: Register, rn: Register, imm: u12, shift: bool) Instruction { |
| | 893 | return addSubtractImmediate(0b0, 0b0, rd, rn, imm, shift); |
| | 894 | } |
| | 895 | |
| | 896 | pub fn adds(rd: Register, rn: Register, imm: u12, shift: bool) Instruction { |
| | 897 | return addSubtractImmediate(0b0, 0b1, rd, rn, imm, shift); |
| | 898 | } |
| | 899 | |
| | 900 | pub fn sub(rd: Register, rn: Register, imm: u12, shift: bool) Instruction { |
| | 901 | return addSubtractImmediate(0b1, 0b0, rd, rn, imm, shift); |
| | 902 | } |
| | 903 | |
| | 904 | pub fn subs(rd: Register, rn: Register, imm: u12, shift: bool) Instruction { |
| | 905 | return addSubtractImmediate(0b1, 0b1, rd, rn, imm, shift); |
| | 906 | } |
| 853 | }; | 907 | }; |
| 854 | | 908 | |
| 855 | test "" { | 909 | test "" { |
| ... | @@ -979,6 +1033,14 @@ test "serialize instructions" { | ... | @@ -979,6 +1033,14 @@ test "serialize instructions" { |
| 979 | .inst = Instruction.@"and"(.x0, .x4, .x2, .{ .shift = .lsl, .amount = 0x8 }), | 1033 | .inst = Instruction.@"and"(.x0, .x4, .x2, .{ .shift = .lsl, .amount = 0x8 }), |
| 980 | .expected = 0b1_00_01010_00_0_00010_001000_00100_00000, | 1034 | .expected = 0b1_00_01010_00_0_00010_001000_00100_00000, |
| 981 | }, | 1035 | }, |
| | 1036 | .{ // add x0, x10, #10 |
| | 1037 | .inst = Instruction.add(.x0, .x10, 10, false), |
| | 1038 | .expected = 0b1_0_0_100010_0_0000_0000_1010_01010_00000, |
| | 1039 | }, |
| | 1040 | .{ // subs x0, x5, #11, lsl #12 |
| | 1041 | .inst = Instruction.subs(.x0, .x5, 11, true), |
| | 1042 | .expected = 0b1_1_1_100010_1_0000_0000_1011_00101_00000, |
| | 1043 | }, |
| 982 | }; | 1044 | }; |
| 983 | | 1045 | |
| 984 | for (testcases) |case| { | 1046 | for (testcases) |case| { |