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