authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2022-01-13 17:45:19+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-01-14 00:46:07+01:00
log7e76aab98abe94e01cfd8b01ce288360ed67dbc7
tree8a6f96e1edca471e5571f60be72e5c3b659cd37d
parente945619728110affb389402ff1ce06d65470cdd2

stage2 AArch64: split ldr/str into {ldr,str}_register and _immediate


3 files changed, 132 insertions(+), 110 deletions(-)

src/arch/aarch64/Emit.zig+42-38
...@@ -112,12 +112,19 @@ pub fn emitMir(...@@ -112,12 +112,19 @@ pub fn emitMir(
112 .strb_stack => try emit.mirLoadStoreStack(inst),112 .strb_stack => try emit.mirLoadStoreStack(inst),
113 .strh_stack => try emit.mirLoadStoreStack(inst),113 .strh_stack => try emit.mirLoadStoreStack(inst),
114114
115 .ldr => try emit.mirLoadStoreRegister(inst),115 .ldr_register => try emit.mirLoadStoreRegisterRegister(inst),
116 .ldrb => try emit.mirLoadStoreRegister(inst),116 .ldrb_register => try emit.mirLoadStoreRegisterRegister(inst),
117 .ldrh => try emit.mirLoadStoreRegister(inst),117 .ldrh_register => try emit.mirLoadStoreRegisterRegister(inst),
118 .str => try emit.mirLoadStoreRegister(inst),118 .str_register => try emit.mirLoadStoreRegisterRegister(inst),
119 .strb => try emit.mirLoadStoreRegister(inst),119 .strb_register => try emit.mirLoadStoreRegisterRegister(inst),
120 .strh => try emit.mirLoadStoreRegister(inst),120 .strh_register => try emit.mirLoadStoreRegisterRegister(inst),
121
122 .ldr_immediate => try emit.mirLoadStoreRegisterImmediate(inst),
123 .ldrb_immediate => try emit.mirLoadStoreRegisterImmediate(inst),
124 .ldrh_immediate => try emit.mirLoadStoreRegisterImmediate(inst),
125 .str_immediate => try emit.mirLoadStoreRegisterImmediate(inst),
126 .strb_immediate => try emit.mirLoadStoreRegisterImmediate(inst),
127 .strh_immediate => try emit.mirLoadStoreRegisterImmediate(inst),
121128
122 .mov_register => try emit.mirMoveRegister(inst),129 .mov_register => try emit.mirMoveRegister(inst),
123 .mov_to_from_sp => try emit.mirMoveRegister(inst),130 .mov_to_from_sp => try emit.mirMoveRegister(inst),
...@@ -737,41 +744,38 @@ fn mirLoadStoreStack(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -737,41 +744,38 @@ fn mirLoadStoreStack(emit: *Emit, inst: Mir.Inst.Index) !void {
737 }744 }
738}745}
739746
740fn mirLoadStoreRegister(emit: *Emit, inst: Mir.Inst.Index) !void {747fn mirLoadStoreRegisterImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {
741 const tag = emit.mir.instructions.items(.tag)[inst];748 const tag = emit.mir.instructions.items(.tag)[inst];
742 const load_store_register = emit.mir.instructions.items(.data)[inst].load_store_register;749 const load_store_register_immediate = emit.mir.instructions.items(.data)[inst].load_store_register_immediate;
750 const rt = load_store_register_immediate.rt;
751 const rn = load_store_register_immediate.rn;
752 const offset = Instruction.LoadStoreOffset{ .immediate = load_store_register_immediate.offset };
743753
744 switch (tag) {754 switch (tag) {
745 .ldr => try emit.writeInstruction(Instruction.ldr(755 .ldr_immediate => try emit.writeInstruction(Instruction.ldr(rt, rn, offset)),
746 load_store_register.rt,756 .ldrb_immediate => try emit.writeInstruction(Instruction.ldrb(rt, rn, offset)),
747 load_store_register.rn,757 .ldrh_immediate => try emit.writeInstruction(Instruction.ldrh(rt, rn, offset)),
748 load_store_register.offset,758 .str_immediate => try emit.writeInstruction(Instruction.str(rt, rn, offset)),
749 )),759 .strb_immediate => try emit.writeInstruction(Instruction.strb(rt, rn, offset)),
750 .ldrb => try emit.writeInstruction(Instruction.ldrb(760 .strh_immediate => try emit.writeInstruction(Instruction.strh(rt, rn, offset)),
751 load_store_register.rt,761 else => unreachable,
752 load_store_register.rn,762 }
753 load_store_register.offset,763}
754 )),764
755 .ldrh => try emit.writeInstruction(Instruction.ldrh(765fn mirLoadStoreRegisterRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
756 load_store_register.rt,766 const tag = emit.mir.instructions.items(.tag)[inst];
757 load_store_register.rn,767 const load_store_register_register = emit.mir.instructions.items(.data)[inst].load_store_register_register;
758 load_store_register.offset,768 const rt = load_store_register_register.rt;
759 )),769 const rn = load_store_register_register.rn;
760 .str => try emit.writeInstruction(Instruction.str(770 const offset = Instruction.LoadStoreOffset{ .register = load_store_register_register.offset };
761 load_store_register.rt,771
762 load_store_register.rn,772 switch (tag) {
763 load_store_register.offset,773 .ldr_register => try emit.writeInstruction(Instruction.ldr(rt, rn, offset)),
764 )),774 .ldrb_register => try emit.writeInstruction(Instruction.ldrb(rt, rn, offset)),
765 .strb => try emit.writeInstruction(Instruction.strb(775 .ldrh_register => try emit.writeInstruction(Instruction.ldrh(rt, rn, offset)),
766 load_store_register.rt,776 .str_register => try emit.writeInstruction(Instruction.str(rt, rn, offset)),
767 load_store_register.rn,777 .strb_register => try emit.writeInstruction(Instruction.strb(rt, rn, offset)),
768 load_store_register.offset,778 .strh_register => try emit.writeInstruction(Instruction.strh(rt, rn, offset)),
769 )),
770 .strh => try emit.writeInstruction(Instruction.strh(
771 load_store_register.rt,
772 load_store_register.rn,
773 load_store_register.offset,
774 )),
775 else => unreachable,779 else => unreachable,
776 }780 }
777}781}
src/arch/aarch64/Mir.zig+40-26
...@@ -58,19 +58,22 @@ pub const Inst = struct {...@@ -58,19 +58,22 @@ pub const Inst = struct {
58 ldp,58 ldp,
59 /// Pseudo-instruction: Load from stack59 /// Pseudo-instruction: Load from stack
60 ldr_stack,60 ldr_stack,
61 /// Load Register61 /// Load Register (immediate)
62 // TODO: split into ldr_immediate and ldr_register62 ldr_immediate,
63 ldr,63 /// Load Register (register)
64 ldr_register,
64 /// Pseudo-instruction: Load byte from stack65 /// Pseudo-instruction: Load byte from stack
65 ldrb_stack,66 ldrb_stack,
66 /// Load Register Byte67 /// Load Register Byte (immediate)
67 // TODO: split into ldrb_immediate and ldrb_register68 ldrb_immediate,
68 ldrb,69 /// Load Register Byte (register)
70 ldrb_register,
69 /// Pseudo-instruction: Load halfword from stack71 /// Pseudo-instruction: Load halfword from stack
70 ldrh_stack,72 ldrh_stack,
71 /// Load Register Halfword73 /// Load Register Halfword (immediate)
72 // TODO: split into ldrh_immediate and ldrh_register74 ldrh_immediate,
73 ldrh,75 /// Load Register Halfword (register)
76 ldrh_register,
74 /// Move (to/from SP)77 /// Move (to/from SP)
75 mov_to_from_sp,78 mov_to_from_sp,
76 /// Move (register)79 /// Move (register)
...@@ -91,19 +94,22 @@ pub const Inst = struct {...@@ -91,19 +94,22 @@ pub const Inst = struct {
91 stp,94 stp,
92 /// Pseudo-instruction: Store to stack95 /// Pseudo-instruction: Store to stack
93 str_stack,96 str_stack,
94 /// Store Register97 /// Store Register (immediate)
95 // TODO: split into str_immediate and str_register98 str_immediate,
96 str,99 /// Store Register (register)
100 str_register,
97 /// Pseudo-instruction: Store byte to stack101 /// Pseudo-instruction: Store byte to stack
98 strb_stack,102 strb_stack,
99 /// Store Register Byte103 /// Store Register Byte (immediate)
100 // TODO: split into strb_immediate and strb_register104 strb_immediate,
101 strb,105 /// Store Register Byte (register)
106 strb_register,
102 /// Pseudo-instruction: Store halfword to stack107 /// Pseudo-instruction: Store halfword to stack
103 strh_stack,108 strh_stack,
104 /// Store Register Halfword109 /// Store Register Halfword (immediate)
105 // TODO: split into strh_immediate and strh_register110 strh_immediate,
106 strh,111 /// Store Register Halfword (register)
112 strh_register,
107 /// Subtract (immediate)113 /// Subtract (immediate)
108 sub_immediate,114 sub_immediate,
109 /// Supervisor Call115 /// Supervisor Call
...@@ -195,13 +201,21 @@ pub const Inst = struct {...@@ -195,13 +201,21 @@ pub const Inst = struct {
195 rm: Register,201 rm: Register,
196 cond: bits.Instruction.Condition,202 cond: bits.Instruction.Condition,
197 },203 },
198 /// Two registers and a LoadStoreOffset204 /// Two registers and a LoadStoreOffsetImmediate
199 ///205 ///
200 /// Used by e.g. str_register206 /// Used by e.g. str_register
201 load_store_register: struct {207 load_store_register_immediate: struct {
202 rt: Register,208 rt: Register,
203 rn: Register,209 rn: Register,
204 offset: bits.Instruction.LoadStoreOffset,210 offset: bits.Instruction.LoadStoreOffsetImmediate,
211 },
212 /// Two registers and a LoadStoreOffsetRegister
213 ///
214 /// Used by e.g. str_register
215 load_store_register_register: struct {
216 rt: Register,
217 rn: Register,
218 offset: bits.Instruction.LoadStoreOffsetRegister,
205 },219 },
206 /// A registers and a stack offset220 /// A registers and a stack offset
207 ///221 ///
...@@ -230,11 +244,11 @@ pub const Inst = struct {...@@ -230,11 +244,11 @@ pub const Inst = struct {
230244
231 // Make sure we don't accidentally make instructions bigger than expected.245 // Make sure we don't accidentally make instructions bigger than expected.
232 // Note that in Debug builds, Zig is allowed to insert a secret field for safety checks.246 // Note that in Debug builds, Zig is allowed to insert a secret field for safety checks.
233 // comptime {247 comptime {
234 // if (builtin.mode != .Debug) {248 if (builtin.mode != .Debug) {
235 // assert(@sizeOf(Inst) == 8);249 assert(@sizeOf(Data) == 8);
236 // }250 }
237 // }251 }
238};252};
239253
240pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {254pub fn deinit(mir: *Mir, gpa: std.mem.Allocator) void {
src/arch/aarch64/bits.zig+50-46
...@@ -521,69 +521,73 @@ pub const Instruction = union(enum) {...@@ -521,69 +521,73 @@ pub const Instruction = union(enum) {
521 };521 };
522 }522 }
523523
524 pub const LoadStoreOffsetImmediate = union(enum) {
525 post_index: i9,
526 pre_index: i9,
527 unsigned: u12,
528 };
529
530 pub const LoadStoreOffsetRegister = struct {
531 rm: u5,
532 shift: union(enum) {
533 uxtw: u2,
534 lsl: u2,
535 sxtw: u2,
536 sxtx: u2,
537 },
538 };
539
524 /// Represents the offset operand of a load or store instruction.540 /// Represents the offset operand of a load or store instruction.
525 /// Data can be loaded from memory with either an immediate offset541 /// Data can be loaded from memory with either an immediate offset
526 /// or an offset that is stored in some register.542 /// or an offset that is stored in some register.
527 pub const LoadStoreOffset = union(enum) {543 pub const LoadStoreOffset = union(enum) {
528 Immediate: union(enum) {544 immediate: LoadStoreOffsetImmediate,
529 PostIndex: i9,545 register: LoadStoreOffsetRegister,
530 PreIndex: i9,
531 Unsigned: u12,
532 },
533 Register: struct {
534 rm: u5,
535 shift: union(enum) {
536 Uxtw: u2,
537 Lsl: u2,
538 Sxtw: u2,
539 Sxtx: u2,
540 },
541 },
542546
543 pub const none = LoadStoreOffset{547 pub const none = LoadStoreOffset{
544 .Immediate = .{ .Unsigned = 0 },548 .immediate = .{ .unsigned = 0 },
545 };549 };
546550
547 pub fn toU12(self: LoadStoreOffset) u12 {551 pub fn toU12(self: LoadStoreOffset) u12 {
548 return switch (self) {552 return switch (self) {
549 .Immediate => |imm_type| switch (imm_type) {553 .immediate => |imm_type| switch (imm_type) {
550 .PostIndex => |v| (@intCast(u12, @bitCast(u9, v)) << 2) + 1,554 .post_index => |v| (@intCast(u12, @bitCast(u9, v)) << 2) + 1,
551 .PreIndex => |v| (@intCast(u12, @bitCast(u9, v)) << 2) + 3,555 .pre_index => |v| (@intCast(u12, @bitCast(u9, v)) << 2) + 3,
552 .Unsigned => |v| v,556 .unsigned => |v| v,
553 },557 },
554 .Register => |r| switch (r.shift) {558 .register => |r| switch (r.shift) {
555 .Uxtw => |v| (@intCast(u12, r.rm) << 6) + (@intCast(u12, v) << 2) + 16 + 2050,559 .uxtw => |v| (@intCast(u12, r.rm) << 6) + (@intCast(u12, v) << 2) + 16 + 2050,
556 .Lsl => |v| (@intCast(u12, r.rm) << 6) + (@intCast(u12, v) << 2) + 24 + 2050,560 .lsl => |v| (@intCast(u12, r.rm) << 6) + (@intCast(u12, v) << 2) + 24 + 2050,
557 .Sxtw => |v| (@intCast(u12, r.rm) << 6) + (@intCast(u12, v) << 2) + 48 + 2050,561 .sxtw => |v| (@intCast(u12, r.rm) << 6) + (@intCast(u12, v) << 2) + 48 + 2050,
558 .Sxtx => |v| (@intCast(u12, r.rm) << 6) + (@intCast(u12, v) << 2) + 56 + 2050,562 .sxtx => |v| (@intCast(u12, r.rm) << 6) + (@intCast(u12, v) << 2) + 56 + 2050,
559 },563 },
560 };564 };
561 }565 }
562566
563 pub fn imm(offset: u12) LoadStoreOffset {567 pub fn imm(offset: u12) LoadStoreOffset {
564 return .{568 return .{
565 .Immediate = .{ .Unsigned = offset },569 .immediate = .{ .unsigned = offset },
566 };570 };
567 }571 }
568572
569 pub fn imm_post_index(offset: i9) LoadStoreOffset {573 pub fn imm_post_index(offset: i9) LoadStoreOffset {
570 return .{574 return .{
571 .Immediate = .{ .PostIndex = offset },575 .immediate = .{ .post_index = offset },
572 };576 };
573 }577 }
574578
575 pub fn imm_pre_index(offset: i9) LoadStoreOffset {579 pub fn imm_pre_index(offset: i9) LoadStoreOffset {
576 return .{580 return .{
577 .Immediate = .{ .PreIndex = offset },581 .immediate = .{ .pre_index = offset },
578 };582 };
579 }583 }
580584
581 pub fn reg(rm: Register) LoadStoreOffset {585 pub fn reg(rm: Register) LoadStoreOffset {
582 return .{586 return .{
583 .Register = .{587 .register = .{
584 .rm = rm.id(),588 .rm = rm.id(),
585 .shift = .{589 .shift = .{
586 .Lsl = 0,590 .lsl = 0,
587 },591 },
588 },592 },
589 };593 };
...@@ -592,10 +596,10 @@ pub const Instruction = union(enum) {...@@ -592,10 +596,10 @@ pub const Instruction = union(enum) {
592 pub fn reg_uxtw(rm: Register, shift: u2) LoadStoreOffset {596 pub fn reg_uxtw(rm: Register, shift: u2) LoadStoreOffset {
593 assert(rm.size() == 32 and (shift == 0 or shift == 2));597 assert(rm.size() == 32 and (shift == 0 or shift == 2));
594 return .{598 return .{
595 .Register = .{599 .register = .{
596 .rm = rm.id(),600 .rm = rm.id(),
597 .shift = .{601 .shift = .{
598 .Uxtw = shift,602 .uxtw = shift,
599 },603 },
600 },604 },
601 };605 };
...@@ -604,10 +608,10 @@ pub const Instruction = union(enum) {...@@ -604,10 +608,10 @@ pub const Instruction = union(enum) {
604 pub fn reg_lsl(rm: Register, shift: u2) LoadStoreOffset {608 pub fn reg_lsl(rm: Register, shift: u2) LoadStoreOffset {
605 assert(rm.size() == 64 and (shift == 0 or shift == 3));609 assert(rm.size() == 64 and (shift == 0 or shift == 3));
606 return .{610 return .{
607 .Register = .{611 .register = .{
608 .rm = rm.id(),612 .rm = rm.id(),
609 .shift = .{613 .shift = .{
610 .Lsl = shift,614 .lsl = shift,
611 },615 },
612 },616 },
613 };617 };
...@@ -616,10 +620,10 @@ pub const Instruction = union(enum) {...@@ -616,10 +620,10 @@ pub const Instruction = union(enum) {
616 pub fn reg_sxtw(rm: Register, shift: u2) LoadStoreOffset {620 pub fn reg_sxtw(rm: Register, shift: u2) LoadStoreOffset {
617 assert(rm.size() == 32 and (shift == 0 or shift == 2));621 assert(rm.size() == 32 and (shift == 0 or shift == 2));
618 return .{622 return .{
619 .Register = .{623 .register = .{
620 .rm = rm.id(),624 .rm = rm.id(),
621 .shift = .{625 .shift = .{
622 .Sxtw = shift,626 .sxtw = shift,
623 },627 },
624 },628 },
625 };629 };
...@@ -628,10 +632,10 @@ pub const Instruction = union(enum) {...@@ -628,10 +632,10 @@ pub const Instruction = union(enum) {
628 pub fn reg_sxtx(rm: Register, shift: u2) LoadStoreOffset {632 pub fn reg_sxtx(rm: Register, shift: u2) LoadStoreOffset {
629 assert(rm.size() == 64 and (shift == 0 or shift == 3));633 assert(rm.size() == 64 and (shift == 0 or shift == 3));
630 return .{634 return .{
631 .Register = .{635 .register = .{
632 .rm = rm.id(),636 .rm = rm.id(),
633 .shift = .{637 .shift = .{
634 .Sxtx = shift,638 .sxtx = shift,
635 },639 },
636 },640 },
637 };641 };
...@@ -663,8 +667,8 @@ pub const Instruction = union(enum) {...@@ -663,8 +667,8 @@ pub const Instruction = union(enum) {
663 const off = offset.toU12();667 const off = offset.toU12();
664 const op1: u2 = blk: {668 const op1: u2 = blk: {
665 switch (offset) {669 switch (offset) {
666 .Immediate => |imm| switch (imm) {670 .immediate => |imm| switch (imm) {
667 .Unsigned => break :blk 0b01,671 .unsigned => break :blk 0b01,
668 else => {},672 else => {},
669 },673 },
670 else => {},674 else => {},
...@@ -1023,26 +1027,26 @@ pub const Instruction = union(enum) {...@@ -1023,26 +1027,26 @@ pub const Instruction = union(enum) {
10231027
1024 pub const LoadStorePairOffset = struct {1028 pub const LoadStorePairOffset = struct {
1025 encoding: enum(u2) {1029 encoding: enum(u2) {
1026 PostIndex = 0b01,1030 post_index = 0b01,
1027 Signed = 0b10,1031 signed = 0b10,
1028 PreIndex = 0b11,1032 pre_index = 0b11,
1029 },1033 },
1030 offset: i9,1034 offset: i9,
10311035
1032 pub fn none() LoadStorePairOffset {1036 pub fn none() LoadStorePairOffset {
1033 return .{ .encoding = .Signed, .offset = 0 };1037 return .{ .encoding = .signed, .offset = 0 };
1034 }1038 }
10351039
1036 pub fn post_index(imm: i9) LoadStorePairOffset {1040 pub fn post_index(imm: i9) LoadStorePairOffset {
1037 return .{ .encoding = .PostIndex, .offset = imm };1041 return .{ .encoding = .post_index, .offset = imm };
1038 }1042 }
10391043
1040 pub fn pre_index(imm: i9) LoadStorePairOffset {1044 pub fn pre_index(imm: i9) LoadStorePairOffset {
1041 return .{ .encoding = .PreIndex, .offset = imm };1045 return .{ .encoding = .pre_index, .offset = imm };
1042 }1046 }
10431047
1044 pub fn signed(imm: i9) LoadStorePairOffset {1048 pub fn signed(imm: i9) LoadStorePairOffset {
1045 return .{ .encoding = .Signed, .offset = imm };1049 return .{ .encoding = .signed, .offset = imm };
1046 }1050 }
1047 };1051 };
10481052