authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-27 12:51:46+01:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-02-27 21:38:55+01:00
log528008a981cb3c63baf1fa7ce7f888f68be725ee
tree451b3ab302ac44019fe35faa598d6835e254f01d
parent139b731d82d0b851c8fb2e6dbb48b735e63eecd1
signaturelock-open Commit is signed but in an unrecognized format.

stage2 ARM: reduce Mir.Inst.Data to 8 bytes


2 files changed, 54 insertions(+), 35 deletions(-)

src/arch/arm/Mir.zig+5-7
......@@ -118,8 +118,6 @@ pub const Inst = struct {
118118 /// All instructions have a 8-byte payload, which is contained within
119119 /// this union. `Tag` determines which union field is active, as well as
120120 /// how to interpret the data within.
121 // TODO flatten down Data (remove use of tagged unions) to make it
122 // 8 bytes only
123121 pub const Data = union {
124122 /// No additional data
125123 ///
......@@ -231,11 +229,11 @@ pub const Inst = struct {
231229
232230 // Make sure we don't accidentally make instructions bigger than expected.
233231 // Note that in Debug builds, Zig is allowed to insert a secret field for safety checks.
234 // comptime {
235 // if (builtin.mode != .Debug) {
236 // assert(@sizeOf(Data) == 8);
237 // }
238 // }
232 comptime {
233 if (builtin.mode != .Debug) {
234 assert(@sizeOf(Data) == 8);
235 }
236 }
239237};
240238
241239pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
src/arch/arm/bits.zig+49-28
......@@ -469,6 +469,23 @@ pub const Instruction = union(enum) {
469469 }
470470 };
471471
472 pub const AddressingMode = enum {
473 /// [<Rn>, <offset>]
474 ///
475 /// Address = Rn + offset
476 offset,
477 /// [<Rn>, <offset>]!
478 ///
479 /// Address = Rn + offset
480 /// Rn = Rn + offset
481 pre_index,
482 /// [<Rn>], <offset>
483 ///
484 /// Address = Rn
485 /// Rn = Rn + offset
486 post_index,
487 };
488
472489 /// Represents the offset operand of a load or store
473490 /// instruction. Data can be loaded from memory with either an
474491 /// immediate offset or an offset that is stored in some register.
......@@ -730,10 +747,9 @@ pub const Instruction = union(enum) {
730747 rd: Register,
731748 rn: Register,
732749 offset: Offset,
733 pre_index: bool,
750 mode: AddressingMode,
734751 positive: bool,
735752 byte_word: u1,
736 write_back: bool,
737753 load_store: u1,
738754 ) Instruction {
739755 return Instruction{
......@@ -743,10 +759,16 @@ pub const Instruction = union(enum) {
743759 .rd = rd.id(),
744760 .offset = offset.toU12(),
745761 .load_store = load_store,
746 .write_back = @boolToInt(write_back),
762 .write_back = switch (mode) {
763 .offset => 0b0,
764 .pre_index, .post_index => 0b1,
765 },
747766 .byte_word = byte_word,
748767 .up_down = @boolToInt(positive),
749 .pre_post = @boolToInt(pre_index),
768 .pre_post = switch (mode) {
769 .offset, .pre_index => 0b1,
770 .post_index => 0b0,
771 },
750772 .imm = @boolToInt(offset != .immediate),
751773 },
752774 };
......@@ -754,9 +776,8 @@ pub const Instruction = union(enum) {
754776
755777 fn extraLoadStore(
756778 cond: Condition,
757 pre_index: bool,
779 mode: AddressingMode,
758780 positive: bool,
759 write_back: bool,
760781 o1: u1,
761782 op2: u2,
762783 rn: Register,
......@@ -780,10 +801,16 @@ pub const Instruction = union(enum) {
780801 .rt = rt.id(),
781802 .rn = rn.id(),
782803 .o1 = o1,
783 .write_back = @boolToInt(write_back),
804 .write_back = switch (mode) {
805 .offset => 0b0,
806 .pre_index, .post_index => 0b1,
807 },
784808 .imm = @boolToInt(offset == .immediate),
785809 .up_down = @boolToInt(positive),
786 .pre_index = @boolToInt(pre_index),
810 .pre_index = switch (mode) {
811 .offset, .pre_index => 0b1,
812 .post_index => 0b0,
813 },
787814 .cond = @enumToInt(cond),
788815 },
789816 };
......@@ -1091,51 +1118,49 @@ pub const Instruction = union(enum) {
10911118 // Single data transfer
10921119
10931120 pub const OffsetArgs = struct {
1094 pre_index: bool = true,
1121 mode: AddressingMode = .offset,
10951122 positive: bool = true,
10961123 offset: Offset,
1097 write_back: bool = false,
10981124 };
10991125
11001126 pub fn ldr(cond: Condition, rd: Register, rn: Register, args: OffsetArgs) Instruction {
1101 return singleDataTransfer(cond, rd, rn, args.offset, args.pre_index, args.positive, 0, args.write_back, 1);
1127 return singleDataTransfer(cond, rd, rn, args.offset, args.mode, args.positive, 0, 1);
11021128 }
11031129
11041130 pub fn ldrb(cond: Condition, rd: Register, rn: Register, args: OffsetArgs) Instruction {
1105 return singleDataTransfer(cond, rd, rn, args.offset, args.pre_index, args.positive, 1, args.write_back, 1);
1131 return singleDataTransfer(cond, rd, rn, args.offset, args.mode, args.positive, 1, 1);
11061132 }
11071133
11081134 pub fn str(cond: Condition, rd: Register, rn: Register, args: OffsetArgs) Instruction {
1109 return singleDataTransfer(cond, rd, rn, args.offset, args.pre_index, args.positive, 0, args.write_back, 0);
1135 return singleDataTransfer(cond, rd, rn, args.offset, args.mode, args.positive, 0, 0);
11101136 }
11111137
11121138 pub fn strb(cond: Condition, rd: Register, rn: Register, args: OffsetArgs) Instruction {
1113 return singleDataTransfer(cond, rd, rn, args.offset, args.pre_index, args.positive, 1, args.write_back, 0);
1139 return singleDataTransfer(cond, rd, rn, args.offset, args.mode, args.positive, 1, 0);
11141140 }
11151141
11161142 // Extra load/store
11171143
11181144 pub const ExtraLoadStoreOffsetArgs = struct {
1119 pre_index: bool = true,
1145 mode: AddressingMode = .offset,
11201146 positive: bool = true,
11211147 offset: ExtraLoadStoreOffset,
1122 write_back: bool = false,
11231148 };
11241149
11251150 pub fn strh(cond: Condition, rt: Register, rn: Register, args: ExtraLoadStoreOffsetArgs) Instruction {
1126 return extraLoadStore(cond, args.pre_index, args.positive, args.write_back, 0b0, 0b01, rn, rt, args.offset);
1151 return extraLoadStore(cond, args.mode, args.positive, 0b0, 0b01, rn, rt, args.offset);
11271152 }
11281153
11291154 pub fn ldrh(cond: Condition, rt: Register, rn: Register, args: ExtraLoadStoreOffsetArgs) Instruction {
1130 return extraLoadStore(cond, args.pre_index, args.positive, args.write_back, 0b1, 0b01, rn, rt, args.offset);
1155 return extraLoadStore(cond, args.mode, args.positive, 0b1, 0b01, rn, rt, args.offset);
11311156 }
11321157
11331158 pub fn ldrsh(cond: Condition, rt: Register, rn: Register, args: ExtraLoadStoreOffsetArgs) Instruction {
1134 return extraLoadStore(cond, args.pre_index, args.positive, args.write_back, 0b1, 0b11, rn, rt, args.offset);
1159 return extraLoadStore(cond, args.mode, args.positive, 0b1, 0b11, rn, rt, args.offset);
11351160 }
11361161
11371162 pub fn ldrsb(cond: Condition, rt: Register, rn: Register, args: ExtraLoadStoreOffsetArgs) Instruction {
1138 return extraLoadStore(cond, args.pre_index, args.positive, args.write_back, 0b1, 0b10, rn, rt, args.offset);
1163 return extraLoadStore(cond, args.mode, args.positive, 0b1, 0b10, rn, rt, args.offset);
11391164 }
11401165
11411166 // Block data transfer
......@@ -1234,10 +1259,9 @@ pub const Instruction = union(enum) {
12341259 } else if (args.len == 1) {
12351260 const reg = args[0];
12361261 return ldr(cond, reg, .sp, .{
1237 .pre_index = false,
1262 .mode = .post_index,
12381263 .positive = true,
12391264 .offset = Offset.imm(4),
1240 .write_back = false,
12411265 });
12421266 } else {
12431267 var register_list: u16 = 0;
......@@ -1259,10 +1283,9 @@ pub const Instruction = union(enum) {
12591283 } else if (args.len == 1) {
12601284 const reg = args[0];
12611285 return str(cond, reg, .sp, .{
1262 .pre_index = true,
1286 .mode = .pre_index,
12631287 .positive = false,
12641288 .offset = Offset.imm(4),
1265 .write_back = true,
12661289 });
12671290 } else {
12681291 var register_list: u16 = 0;
......@@ -1447,10 +1470,9 @@ test "aliases" {
14471470 .{ // pop { r6 }
14481471 .actual = Instruction.pop(.al, .{.r6}),
14491472 .expected = Instruction.ldr(.al, .r6, .sp, .{
1450 .pre_index = false,
1473 .mode = .post_index,
14511474 .positive = true,
14521475 .offset = Instruction.Offset.imm(4),
1453 .write_back = false,
14541476 }),
14551477 },
14561478 .{ // pop { r1, r5 }
......@@ -1460,10 +1482,9 @@ test "aliases" {
14601482 .{ // push { r3 }
14611483 .actual = Instruction.push(.al, .{.r3}),
14621484 .expected = Instruction.str(.al, .r3, .sp, .{
1463 .pre_index = true,
1485 .mode = .pre_index,
14641486 .positive = false,
14651487 .offset = Instruction.Offset.imm(4),
1466 .write_back = true,
14671488 }),
14681489 },
14691490 .{ // push { r0, r2 }