authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-12-09 07:39:26+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-12-09 17:20:14+01:00
log21dae538caa5eac71b52be5da59d3a18c05b3a89
treef31a1e987320c2ffa58a2d3bf69e59758dcc2213
parenta01d55e801c91b5f8b6beb1ae88640e16ffdf058

stage2+aarch64: add load and store pair of registers instructions


1 files changed, 97 insertions(+), 1 deletions(-)

src/codegen/aarch64.zig+97-1
...@@ -19,7 +19,7 @@ pub const Register = enum(u6) {...@@ -19,7 +19,7 @@ pub const Register = enum(u6) {
19 w16, w17, w18, w19, w20, w21, w22, w23,19 w16, w17, w18, w19, w20, w21, w22, w23,
20 w24, w25, w26, w27, w28, w29, w30, wzr,20 w24, w25, w26, w27, w28, w29, w30, wzr,
2121
22 pub const sp = .xzr;22 pub const sp = Register.xzr;
2323
24 pub fn id(self: Register) u5 {24 pub fn id(self: Register) u5 {
25 return @truncate(u5, @enumToInt(self));25 return @truncate(u5, @enumToInt(self));
...@@ -72,6 +72,9 @@ test "Register.id" {...@@ -72,6 +72,9 @@ test "Register.id" {
7272
73 testing.expectEqual(@as(u5, 31), Register.xzr.id());73 testing.expectEqual(@as(u5, 31), Register.xzr.id());
74 testing.expectEqual(@as(u5, 31), Register.wzr.id());74 testing.expectEqual(@as(u5, 31), Register.wzr.id());
75
76 testing.expectEqual(@as(u5, 31), Register.sp.id());
77 testing.expectEqual(@as(u5, 31), Register.sp.id());
75}78}
7679
77test "Register.size" {80test "Register.size" {
...@@ -232,6 +235,16 @@ pub const Instruction = union(enum) {...@@ -232,6 +235,16 @@ pub const Instruction = union(enum) {
232 fixed: u4 = 0b111_0,235 fixed: u4 = 0b111_0,
233 size: u2,236 size: u2,
234 },237 },
238 LoadStorePairOfRegisters: packed struct {
239 rt1: u5,
240 rn: u5,
241 rt2: u5,
242 imm7: u7,
243 load: u1,
244 encoding: u2,
245 fixed: u5 = 0b101_0_0,
246 opc: u2,
247 },
235 LoadLiteral: packed struct {248 LoadLiteral: packed struct {
236 rt: u5,249 rt: u5,
237 imm19: u19,250 imm19: u19,
...@@ -268,6 +281,7 @@ pub const Instruction = union(enum) {...@@ -268,6 +281,7 @@ pub const Instruction = union(enum) {
268 .MoveWideImmediate => |v| @bitCast(u32, v),281 .MoveWideImmediate => |v| @bitCast(u32, v),
269 .PCRelativeAddress => |v| @bitCast(u32, v),282 .PCRelativeAddress => |v| @bitCast(u32, v),
270 .LoadStoreRegister => |v| @bitCast(u32, v),283 .LoadStoreRegister => |v| @bitCast(u32, v),
284 .LoadStorePairOfRegisters => |v| @bitCast(u32, v),
271 .LoadLiteral => |v| @bitCast(u32, v),285 .LoadLiteral => |v| @bitCast(u32, v),
272 .ExceptionGeneration => |v| @bitCast(u32, v),286 .ExceptionGeneration => |v| @bitCast(u32, v),
273 .UnconditionalBranchRegister => |v| @bitCast(u32, v),287 .UnconditionalBranchRegister => |v| @bitCast(u32, v),
...@@ -542,6 +556,46 @@ pub const Instruction = union(enum) {...@@ -542,6 +556,46 @@ pub const Instruction = union(enum) {
542 }556 }
543 }557 }
544558
559 fn loadStorePairOfRegisters(
560 rt1: Register,
561 rt2: Register,
562 rn: Register,
563 imm7: i7,
564 encoding: u2,
565 load: bool,
566 ) Instruction {
567 const imm7_u: u7 = @bitCast(u7, imm7);
568 switch (rt1.size()) {
569 32 => {
570 return Instruction{
571 .LoadStorePairOfRegisters = .{
572 .rt1 = rt1.id(),
573 .rn = rn.id(),
574 .rt2 = rt2.id(),
575 .imm7 = imm7_u,
576 .load = @boolToInt(load),
577 .encoding = encoding,
578 .opc = 0b00,
579 },
580 };
581 },
582 64 => {
583 return Instruction{
584 .LoadStorePairOfRegisters = .{
585 .rt1 = rt1.id(),
586 .rn = rn.id(),
587 .rt2 = rt2.id(),
588 .imm7 = imm7_u,
589 .load = @boolToInt(load),
590 .encoding = encoding,
591 .opc = 0b10,
592 },
593 };
594 },
595 else => unreachable, // unexpected register size
596 }
597 }
598
545 fn loadLiteral(rt: Register, imm19: u19) Instruction {599 fn loadLiteral(rt: Register, imm19: u19) Instruction {
546 switch (rt.size()) {600 switch (rt.size()) {
547 32 => {601 32 => {
...@@ -670,6 +724,29 @@ pub const Instruction = union(enum) {...@@ -670,6 +724,29 @@ pub const Instruction = union(enum) {
670 return loadStoreRegister(rt, rn, args.offset, false);724 return loadStoreRegister(rt, rn, args.offset, false);
671 }725 }
672726
727 // Load or store pair of registers
728
729 pub const LoadStorePairEncoding = enum(u2) {
730 PostIndex = 0b01,
731 SignedOffset = 0b10,
732 PreIndex = 0b11,
733 };
734 pub fn ldp(rt1: Register, rt2: Register, rn: Register, imm: i7, encoding: LoadStorePairEncoding) Instruction {
735 return loadStorePairOfRegisters(rt1, rt2, rn, imm, @enumToInt(encoding), true);
736 }
737
738 pub fn ldnp(rt1: Register, rt2: Register, rn: Register, imm: i7) Instruction {
739 return loadStorePairOfRegisters(rt1, rt2, rn, imm, 0, true);
740 }
741
742 pub fn stp(rt1: Register, rt2: Register, rn: Register, imm: i7, encoding: LoadStorePairEncoding) Instruction {
743 return loadStorePairOfRegisters(rt1, rt2, rn, imm, @enumToInt(encoding), false);
744 }
745
746 pub fn stnp(rt1: Register, rt2: Register, rn: Register, imm: i7) Instruction {
747 return loadStorePairOfRegisters(rt1, rt2, rn, imm, 0, false);
748 }
749
673 // Exception generation750 // Exception generation
674751
675 pub fn svc(imm16: u16) Instruction {752 pub fn svc(imm16: u16) Instruction {
...@@ -826,10 +903,29 @@ test "serialize instructions" {...@@ -826,10 +903,29 @@ test "serialize instructions" {
826 .inst = Instruction.adrp(.x2, -0x8),903 .inst = Instruction.adrp(.x2, -0x8),
827 .expected = 0b1_00_10000_1111111111111111110_00010,904 .expected = 0b1_00_10000_1111111111111111110_00010,
828 },905 },
906 .{ // stp x1, x2, [sp, #1]
907 .inst = Instruction.stp(.x1, .x2, Register.sp, 1, .SignedOffset),
908 .expected = 0b10_101_0_010_0_0000001_00010_11111_00001,
909 },
910 .{ // stp x1, x2, [sp, #-16]
911 .inst = Instruction.stp(.x1, .x2, Register.sp, -16, .SignedOffset),
912 .expected = 0b10_101_0_010_0_1110000_00010_11111_00001,
913 },
914 .{ // ldp x1, x2, [sp, #1]
915 .inst = Instruction.ldp(.x1, .x2, Register.sp, 1, .SignedOffset),
916 .expected = 0b10_101_0_010_1_0000001_00010_11111_00001,
917 },
918 .{ // ldp x1, x2, [sp, #16]
919 .inst = Instruction.ldp(.x1, .x2, Register.sp, 16, .SignedOffset),
920 .expected = 0b10_101_0_010_1_0010000_00010_11111_00001,
921 },
829 };922 };
830923
831 for (testcases) |case| {924 for (testcases) |case| {
832 const actual = case.inst.toU32();925 const actual = case.inst.toU32();
926 if (case.expected != actual) {
927 std.debug.print("0b{b} != 0b{b}\n", .{ case.expected, actual });
928 }
833 testing.expectEqual(case.expected, actual);929 testing.expectEqual(case.expected, actual);
834 }930 }
835}931}