| ... | @@ -742,27 +742,17 @@ pub const Instruction = union(enum) { | ... | @@ -742,27 +742,17 @@ pub const Instruction = union(enum) { |
| 742 | } | 742 | } |
| 743 | | 743 | |
| 744 | fn loadLiteral(rt: Register, imm19: u19) Instruction { | 744 | fn loadLiteral(rt: Register, imm19: u19) Instruction { |
| 745 | switch (rt.size()) { | 745 | return Instruction{ |
| 746 | 32 => { | 746 | .load_literal = .{ |
| 747 | return Instruction{ | 747 | .rt = rt.id(), |
| 748 | .load_literal = .{ | 748 | .imm19 = imm19, |
| 749 | .rt = rt.id(), | 749 | .opc = switch (rt.size()) { |
| 750 | .imm19 = imm19, | 750 | 32 => 0b00, |
| 751 | .opc = 0b00, | 751 | 64 => 0b01, |
| 752 | }, | 752 | else => unreachable, // unexpected register size |
| 753 | }; | 753 | }, |
| 754 | }, | | |
| 755 | 64 => { | | |
| 756 | return Instruction{ | | |
| 757 | .load_literal = .{ | | |
| 758 | .rt = rt.id(), | | |
| 759 | .imm19 = imm19, | | |
| 760 | .opc = 0b01, | | |
| 761 | }, | | |
| 762 | }; | | |
| 763 | }, | 754 | }, |
| 764 | else => unreachable, // unexpected register size | 755 | }; |
| 765 | } | | |
| 766 | } | 756 | } |
| 767 | | 757 | |
| 768 | fn exceptionGeneration( | 758 | fn exceptionGeneration( |
| ... | @@ -1001,43 +991,32 @@ pub const Instruction = union(enum) { | ... | @@ -1001,43 +991,32 @@ pub const Instruction = union(enum) { |
| 1001 | | 991 | |
| 1002 | // Load or store register | 992 | // Load or store register |
| 1003 | | 993 | |
| 1004 | pub const LdrArgs = union(enum) { | 994 | pub fn ldrLiteral(rt: Register, literal: u19) Instruction { |
| 1005 | register: struct { | 995 | return loadLiteral(rt, literal); |
| 1006 | rn: Register, | | |
| 1007 | offset: LoadStoreOffset = LoadStoreOffset.none, | | |
| 1008 | }, | | |
| 1009 | literal: u19, | | |
| 1010 | }; | | |
| 1011 | | | |
| 1012 | pub fn ldr(rt: Register, args: LdrArgs) Instruction { | | |
| 1013 | switch (args) { | | |
| 1014 | .register => |info| return loadStoreRegister(rt, info.rn, info.offset, .ldr), | | |
| 1015 | .literal => |literal| return loadLiteral(rt, literal), | | |
| 1016 | } | | |
| 1017 | } | 996 | } |
| 1018 | | 997 | |
| 1019 | pub fn ldrh(rt: Register, rn: Register, args: StrArgs) Instruction { | 998 | pub fn ldr(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction { |
| 1020 | return loadStoreRegister(rt, rn, args.offset, .ldrh); | 999 | return loadStoreRegister(rt, rn, offset, .ldr); |
| 1021 | } | 1000 | } |
| 1022 | | 1001 | |
| 1023 | pub fn ldrb(rt: Register, rn: Register, args: StrArgs) Instruction { | 1002 | pub fn ldrh(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction { |
| 1024 | return loadStoreRegister(rt, rn, args.offset, .ldrb); | 1003 | return loadStoreRegister(rt, rn, offset, .ldrh); |
| 1025 | } | 1004 | } |
| 1026 | | 1005 | |
| 1027 | pub const StrArgs = struct { | 1006 | pub fn ldrb(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction { |
| 1028 | offset: LoadStoreOffset = LoadStoreOffset.none, | 1007 | return loadStoreRegister(rt, rn, offset, .ldrb); |
| 1029 | }; | 1008 | } |
| 1030 | | 1009 | |
| 1031 | pub fn str(rt: Register, rn: Register, args: StrArgs) Instruction { | 1010 | pub fn str(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction { |
| 1032 | return loadStoreRegister(rt, rn, args.offset, .str); | 1011 | return loadStoreRegister(rt, rn, offset, .str); |
| 1033 | } | 1012 | } |
| 1034 | | 1013 | |
| 1035 | pub fn strh(rt: Register, rn: Register, args: StrArgs) Instruction { | 1014 | pub fn strh(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction { |
| 1036 | return loadStoreRegister(rt, rn, args.offset, .strh); | 1015 | return loadStoreRegister(rt, rn, offset, .strh); |
| 1037 | } | 1016 | } |
| 1038 | | 1017 | |
| 1039 | pub fn strb(rt: Register, rn: Register, args: StrArgs) Instruction { | 1018 | pub fn strb(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction { |
| 1040 | return loadStoreRegister(rt, rn, args.offset, .strb); | 1019 | return loadStoreRegister(rt, rn, offset, .strb); |
| 1041 | } | 1020 | } |
| 1042 | | 1021 | |
| 1043 | // Load or store pair of registers | 1022 | // Load or store pair of registers |
| ... | @@ -1324,47 +1303,47 @@ test "serialize instructions" { | ... | @@ -1324,47 +1303,47 @@ test "serialize instructions" { |
| 1324 | .expected = 0b1_00101_00_0000_0000_0000_0000_0000_0100, | 1303 | .expected = 0b1_00101_00_0000_0000_0000_0000_0000_0100, |
| 1325 | }, | 1304 | }, |
| 1326 | .{ // ldr x2, [x1] | 1305 | .{ // ldr x2, [x1] |
| 1327 | .inst = Instruction.ldr(.x2, .{ .register = .{ .rn = .x1 } }), | 1306 | .inst = Instruction.ldr(.x2, .x1, Instruction.LoadStoreOffset.none), |
| 1328 | .expected = 0b11_111_0_01_01_000000000000_00001_00010, | 1307 | .expected = 0b11_111_0_01_01_000000000000_00001_00010, |
| 1329 | }, | 1308 | }, |
| 1330 | .{ // ldr x2, [x1, #1]! | 1309 | .{ // ldr x2, [x1, #1]! |
| 1331 | .inst = Instruction.ldr(.x2, .{ .register = .{ .rn = .x1, .offset = Instruction.LoadStoreOffset.imm_pre_index(1) } }), | 1310 | .inst = Instruction.ldr(.x2, .x1, Instruction.LoadStoreOffset.imm_pre_index(1)), |
| 1332 | .expected = 0b11_111_0_00_01_0_000000001_11_00001_00010, | 1311 | .expected = 0b11_111_0_00_01_0_000000001_11_00001_00010, |
| 1333 | }, | 1312 | }, |
| 1334 | .{ // ldr x2, [x1], #-1 | 1313 | .{ // ldr x2, [x1], #-1 |
| 1335 | .inst = Instruction.ldr(.x2, .{ .register = .{ .rn = .x1, .offset = Instruction.LoadStoreOffset.imm_post_index(-1) } }), | 1314 | .inst = Instruction.ldr(.x2, .x1, Instruction.LoadStoreOffset.imm_post_index(-1)), |
| 1336 | .expected = 0b11_111_0_00_01_0_111111111_01_00001_00010, | 1315 | .expected = 0b11_111_0_00_01_0_111111111_01_00001_00010, |
| 1337 | }, | 1316 | }, |
| 1338 | .{ // ldr x2, [x1], (x3) | 1317 | .{ // ldr x2, [x1], (x3) |
| 1339 | .inst = Instruction.ldr(.x2, .{ .register = .{ .rn = .x1, .offset = Instruction.LoadStoreOffset.reg(.x3) } }), | 1318 | .inst = Instruction.ldr(.x2, .x1, Instruction.LoadStoreOffset.reg(.x3)), |
| 1340 | .expected = 0b11_111_0_00_01_1_00011_011_0_10_00001_00010, | 1319 | .expected = 0b11_111_0_00_01_1_00011_011_0_10_00001_00010, |
| 1341 | }, | 1320 | }, |
| 1342 | .{ // ldr x2, label | 1321 | .{ // ldr x2, label |
| 1343 | .inst = Instruction.ldr(.x2, .{ .literal = 0x1 }), | 1322 | .inst = Instruction.ldrLiteral(.x2, 0x1), |
| 1344 | .expected = 0b01_011_0_00_0000000000000000001_00010, | 1323 | .expected = 0b01_011_0_00_0000000000000000001_00010, |
| 1345 | }, | 1324 | }, |
| 1346 | .{ // ldrh x7, [x4], #0xaa | 1325 | .{ // ldrh x7, [x4], #0xaa |
| 1347 | .inst = Instruction.ldrh(.x7, .x4, .{ .offset = Instruction.LoadStoreOffset.imm_post_index(0xaa) }), | 1326 | .inst = Instruction.ldrh(.x7, .x4, Instruction.LoadStoreOffset.imm_post_index(0xaa)), |
| 1348 | .expected = 0b01_111_0_00_01_0_010101010_01_00100_00111, | 1327 | .expected = 0b01_111_0_00_01_0_010101010_01_00100_00111, |
| 1349 | }, | 1328 | }, |
| 1350 | .{ // ldrb x9, [x15, #0xff]! | 1329 | .{ // ldrb x9, [x15, #0xff]! |
| 1351 | .inst = Instruction.ldrb(.x9, .x15, .{ .offset = Instruction.LoadStoreOffset.imm_pre_index(0xff) }), | 1330 | .inst = Instruction.ldrb(.x9, .x15, Instruction.LoadStoreOffset.imm_pre_index(0xff)), |
| 1352 | .expected = 0b00_111_0_00_01_0_011111111_11_01111_01001, | 1331 | .expected = 0b00_111_0_00_01_0_011111111_11_01111_01001, |
| 1353 | }, | 1332 | }, |
| 1354 | .{ // str x2, [x1] | 1333 | .{ // str x2, [x1] |
| 1355 | .inst = Instruction.str(.x2, .x1, .{}), | 1334 | .inst = Instruction.str(.x2, .x1, Instruction.LoadStoreOffset.none), |
| 1356 | .expected = 0b11_111_0_01_00_000000000000_00001_00010, | 1335 | .expected = 0b11_111_0_01_00_000000000000_00001_00010, |
| 1357 | }, | 1336 | }, |
| 1358 | .{ // str x2, [x1], (x3) | 1337 | .{ // str x2, [x1], (x3) |
| 1359 | .inst = Instruction.str(.x2, .x1, .{ .offset = Instruction.LoadStoreOffset.reg(.x3) }), | 1338 | .inst = Instruction.str(.x2, .x1, Instruction.LoadStoreOffset.reg(.x3)), |
| 1360 | .expected = 0b11_111_0_00_00_1_00011_011_0_10_00001_00010, | 1339 | .expected = 0b11_111_0_00_00_1_00011_011_0_10_00001_00010, |
| 1361 | }, | 1340 | }, |
| 1362 | .{ // strh w0, [x1] | 1341 | .{ // strh w0, [x1] |
| 1363 | .inst = Instruction.strh(.w0, .x1, .{}), | 1342 | .inst = Instruction.strh(.w0, .x1, Instruction.LoadStoreOffset.none), |
| 1364 | .expected = 0b01_111_0_01_00_000000000000_00001_00000, | 1343 | .expected = 0b01_111_0_01_00_000000000000_00001_00000, |
| 1365 | }, | 1344 | }, |
| 1366 | .{ // strb w8, [x9] | 1345 | .{ // strb w8, [x9] |
| 1367 | .inst = Instruction.strb(.w8, .x9, .{}), | 1346 | .inst = Instruction.strb(.w8, .x9, Instruction.LoadStoreOffset.none), |
| 1368 | .expected = 0b00_111_0_01_00_000000000000_01001_01000, | 1347 | .expected = 0b00_111_0_01_00_000000000000_01001_01000, |
| 1369 | }, | 1348 | }, |
| 1370 | .{ // adr x2, #0x8 | 1349 | .{ // adr x2, #0x8 |