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(
112112 .strb_stack => try emit.mirLoadStoreStack(inst),
113113 .strh_stack => try emit.mirLoadStoreStack(inst),
114114
115 .ldr => try emit.mirLoadStoreRegister(inst),
116 .ldrb => try emit.mirLoadStoreRegister(inst),
117 .ldrh => try emit.mirLoadStoreRegister(inst),
118 .str => try emit.mirLoadStoreRegister(inst),
119 .strb => try emit.mirLoadStoreRegister(inst),
120 .strh => try emit.mirLoadStoreRegister(inst),
115 .ldr_register => try emit.mirLoadStoreRegisterRegister(inst),
116 .ldrb_register => try emit.mirLoadStoreRegisterRegister(inst),
117 .ldrh_register => try emit.mirLoadStoreRegisterRegister(inst),
118 .str_register => try emit.mirLoadStoreRegisterRegister(inst),
119 .strb_register => try emit.mirLoadStoreRegisterRegister(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
122129 .mov_register => try emit.mirMoveRegister(inst),
123130 .mov_to_from_sp => try emit.mirMoveRegister(inst),
......@@ -737,41 +744,38 @@ fn mirLoadStoreStack(emit: *Emit, inst: Mir.Inst.Index) !void {
737744 }
738745}
739746
740fn mirLoadStoreRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
747fn mirLoadStoreRegisterImmediate(emit: *Emit, inst: Mir.Inst.Index) !void {
741748 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
744754 switch (tag) {
745 .ldr => try emit.writeInstruction(Instruction.ldr(
746 load_store_register.rt,
747 load_store_register.rn,
748 load_store_register.offset,
749 )),
750 .ldrb => try emit.writeInstruction(Instruction.ldrb(
751 load_store_register.rt,
752 load_store_register.rn,
753 load_store_register.offset,
754 )),
755 .ldrh => try emit.writeInstruction(Instruction.ldrh(
756 load_store_register.rt,
757 load_store_register.rn,
758 load_store_register.offset,
759 )),
760 .str => try emit.writeInstruction(Instruction.str(
761 load_store_register.rt,
762 load_store_register.rn,
763 load_store_register.offset,
764 )),
765 .strb => try emit.writeInstruction(Instruction.strb(
766 load_store_register.rt,
767 load_store_register.rn,
768 load_store_register.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 )),
755 .ldr_immediate => try emit.writeInstruction(Instruction.ldr(rt, rn, offset)),
756 .ldrb_immediate => try emit.writeInstruction(Instruction.ldrb(rt, rn, offset)),
757 .ldrh_immediate => try emit.writeInstruction(Instruction.ldrh(rt, rn, offset)),
758 .str_immediate => try emit.writeInstruction(Instruction.str(rt, rn, offset)),
759 .strb_immediate => try emit.writeInstruction(Instruction.strb(rt, rn, offset)),
760 .strh_immediate => try emit.writeInstruction(Instruction.strh(rt, rn, offset)),
761 else => unreachable,
762 }
763}
764
765fn mirLoadStoreRegisterRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
766 const tag = emit.mir.instructions.items(.tag)[inst];
767 const load_store_register_register = emit.mir.instructions.items(.data)[inst].load_store_register_register;
768 const rt = load_store_register_register.rt;
769 const rn = load_store_register_register.rn;
770 const offset = Instruction.LoadStoreOffset{ .register = load_store_register_register.offset };
771
772 switch (tag) {
773 .ldr_register => try emit.writeInstruction(Instruction.ldr(rt, rn, offset)),
774 .ldrb_register => try emit.writeInstruction(Instruction.ldrb(rt, rn, offset)),
775 .ldrh_register => try emit.writeInstruction(Instruction.ldrh(rt, rn, offset)),
776 .str_register => try emit.writeInstruction(Instruction.str(rt, rn, offset)),
777 .strb_register => try emit.writeInstruction(Instruction.strb(rt, rn, offset)),
778 .strh_register => try emit.writeInstruction(Instruction.strh(rt, rn, offset)),
775779 else => unreachable,
776780 }
777781}
src/arch/aarch64/Mir.zig+40-26
......@@ -58,19 +58,22 @@ pub const Inst = struct {
5858 ldp,
5959 /// Pseudo-instruction: Load from stack
6060 ldr_stack,
61 /// Load Register
62 // TODO: split into ldr_immediate and ldr_register
63 ldr,
61 /// Load Register (immediate)
62 ldr_immediate,
63 /// Load Register (register)
64 ldr_register,
6465 /// Pseudo-instruction: Load byte from stack
6566 ldrb_stack,
66 /// Load Register Byte
67 // TODO: split into ldrb_immediate and ldrb_register
68 ldrb,
67 /// Load Register Byte (immediate)
68 ldrb_immediate,
69 /// Load Register Byte (register)
70 ldrb_register,
6971 /// Pseudo-instruction: Load halfword from stack
7072 ldrh_stack,
71 /// Load Register Halfword
72 // TODO: split into ldrh_immediate and ldrh_register
73 ldrh,
73 /// Load Register Halfword (immediate)
74 ldrh_immediate,
75 /// Load Register Halfword (register)
76 ldrh_register,
7477 /// Move (to/from SP)
7578 mov_to_from_sp,
7679 /// Move (register)
......@@ -91,19 +94,22 @@ pub const Inst = struct {
9194 stp,
9295 /// Pseudo-instruction: Store to stack
9396 str_stack,
94 /// Store Register
95 // TODO: split into str_immediate and str_register
96 str,
97 /// Store Register (immediate)
98 str_immediate,
99 /// Store Register (register)
100 str_register,
97101 /// Pseudo-instruction: Store byte to stack
98102 strb_stack,
99 /// Store Register Byte
100 // TODO: split into strb_immediate and strb_register
101 strb,
103 /// Store Register Byte (immediate)
104 strb_immediate,
105 /// Store Register Byte (register)
106 strb_register,
102107 /// Pseudo-instruction: Store halfword to stack
103108 strh_stack,
104 /// Store Register Halfword
105 // TODO: split into strh_immediate and strh_register
106 strh,
109 /// Store Register Halfword (immediate)
110 strh_immediate,
111 /// Store Register Halfword (register)
112 strh_register,
107113 /// Subtract (immediate)
108114 sub_immediate,
109115 /// Supervisor Call
......@@ -195,13 +201,21 @@ pub const Inst = struct {
195201 rm: Register,
196202 cond: bits.Instruction.Condition,
197203 },
198 /// Two registers and a LoadStoreOffset
204 /// Two registers and a LoadStoreOffsetImmediate
199205 ///
200206 /// Used by e.g. str_register
201 load_store_register: struct {
207 load_store_register_immediate: struct {
202208 rt: Register,
203209 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,
205219 },
206220 /// A registers and a stack offset
207221 ///
......@@ -230,11 +244,11 @@ pub const Inst = struct {
230244
231245 // Make sure we don't accidentally make instructions bigger than expected.
232246 // Note that in Debug builds, Zig is allowed to insert a secret field for safety checks.
233 // comptime {
234 // if (builtin.mode != .Debug) {
235 // assert(@sizeOf(Inst) == 8);
236 // }
237 // }
247 comptime {
248 if (builtin.mode != .Debug) {
249 assert(@sizeOf(Data) == 8);
250 }
251 }
238252};
239253
240254pub 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) {
521521 };
522522 }
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
524540 /// Represents the offset operand of a load or store instruction.
525541 /// Data can be loaded from memory with either an immediate offset
526542 /// or an offset that is stored in some register.
527543 pub const LoadStoreOffset = union(enum) {
528 Immediate: union(enum) {
529 PostIndex: i9,
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 },
544 immediate: LoadStoreOffsetImmediate,
545 register: LoadStoreOffsetRegister,
542546
543547 pub const none = LoadStoreOffset{
544 .Immediate = .{ .Unsigned = 0 },
548 .immediate = .{ .unsigned = 0 },
545549 };
546550
547551 pub fn toU12(self: LoadStoreOffset) u12 {
548552 return switch (self) {
549 .Immediate => |imm_type| switch (imm_type) {
550 .PostIndex => |v| (@intCast(u12, @bitCast(u9, v)) << 2) + 1,
551 .PreIndex => |v| (@intCast(u12, @bitCast(u9, v)) << 2) + 3,
552 .Unsigned => |v| v,
553 .immediate => |imm_type| switch (imm_type) {
554 .post_index => |v| (@intCast(u12, @bitCast(u9, v)) << 2) + 1,
555 .pre_index => |v| (@intCast(u12, @bitCast(u9, v)) << 2) + 3,
556 .unsigned => |v| v,
553557 },
554 .Register => |r| switch (r.shift) {
555 .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,
557 .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,
558 .register => |r| switch (r.shift) {
559 .uxtw => |v| (@intCast(u12, r.rm) << 6) + (@intCast(u12, v) << 2) + 16 + 2050,
560 .lsl => |v| (@intCast(u12, r.rm) << 6) + (@intCast(u12, v) << 2) + 24 + 2050,
561 .sxtw => |v| (@intCast(u12, r.rm) << 6) + (@intCast(u12, v) << 2) + 48 + 2050,
562 .sxtx => |v| (@intCast(u12, r.rm) << 6) + (@intCast(u12, v) << 2) + 56 + 2050,
559563 },
560564 };
561565 }
562566
563567 pub fn imm(offset: u12) LoadStoreOffset {
564568 return .{
565 .Immediate = .{ .Unsigned = offset },
569 .immediate = .{ .unsigned = offset },
566570 };
567571 }
568572
569573 pub fn imm_post_index(offset: i9) LoadStoreOffset {
570574 return .{
571 .Immediate = .{ .PostIndex = offset },
575 .immediate = .{ .post_index = offset },
572576 };
573577 }
574578
575579 pub fn imm_pre_index(offset: i9) LoadStoreOffset {
576580 return .{
577 .Immediate = .{ .PreIndex = offset },
581 .immediate = .{ .pre_index = offset },
578582 };
579583 }
580584
581585 pub fn reg(rm: Register) LoadStoreOffset {
582586 return .{
583 .Register = .{
587 .register = .{
584588 .rm = rm.id(),
585589 .shift = .{
586 .Lsl = 0,
590 .lsl = 0,
587591 },
588592 },
589593 };
......@@ -592,10 +596,10 @@ pub const Instruction = union(enum) {
592596 pub fn reg_uxtw(rm: Register, shift: u2) LoadStoreOffset {
593597 assert(rm.size() == 32 and (shift == 0 or shift == 2));
594598 return .{
595 .Register = .{
599 .register = .{
596600 .rm = rm.id(),
597601 .shift = .{
598 .Uxtw = shift,
602 .uxtw = shift,
599603 },
600604 },
601605 };
......@@ -604,10 +608,10 @@ pub const Instruction = union(enum) {
604608 pub fn reg_lsl(rm: Register, shift: u2) LoadStoreOffset {
605609 assert(rm.size() == 64 and (shift == 0 or shift == 3));
606610 return .{
607 .Register = .{
611 .register = .{
608612 .rm = rm.id(),
609613 .shift = .{
610 .Lsl = shift,
614 .lsl = shift,
611615 },
612616 },
613617 };
......@@ -616,10 +620,10 @@ pub const Instruction = union(enum) {
616620 pub fn reg_sxtw(rm: Register, shift: u2) LoadStoreOffset {
617621 assert(rm.size() == 32 and (shift == 0 or shift == 2));
618622 return .{
619 .Register = .{
623 .register = .{
620624 .rm = rm.id(),
621625 .shift = .{
622 .Sxtw = shift,
626 .sxtw = shift,
623627 },
624628 },
625629 };
......@@ -628,10 +632,10 @@ pub const Instruction = union(enum) {
628632 pub fn reg_sxtx(rm: Register, shift: u2) LoadStoreOffset {
629633 assert(rm.size() == 64 and (shift == 0 or shift == 3));
630634 return .{
631 .Register = .{
635 .register = .{
632636 .rm = rm.id(),
633637 .shift = .{
634 .Sxtx = shift,
638 .sxtx = shift,
635639 },
636640 },
637641 };
......@@ -663,8 +667,8 @@ pub const Instruction = union(enum) {
663667 const off = offset.toU12();
664668 const op1: u2 = blk: {
665669 switch (offset) {
666 .Immediate => |imm| switch (imm) {
667 .Unsigned => break :blk 0b01,
670 .immediate => |imm| switch (imm) {
671 .unsigned => break :blk 0b01,
668672 else => {},
669673 },
670674 else => {},
......@@ -1023,26 +1027,26 @@ pub const Instruction = union(enum) {
10231027
10241028 pub const LoadStorePairOffset = struct {
10251029 encoding: enum(u2) {
1026 PostIndex = 0b01,
1027 Signed = 0b10,
1028 PreIndex = 0b11,
1030 post_index = 0b01,
1031 signed = 0b10,
1032 pre_index = 0b11,
10291033 },
10301034 offset: i9,
10311035
10321036 pub fn none() LoadStorePairOffset {
1033 return .{ .encoding = .Signed, .offset = 0 };
1037 return .{ .encoding = .signed, .offset = 0 };
10341038 }
10351039
10361040 pub fn post_index(imm: i9) LoadStorePairOffset {
1037 return .{ .encoding = .PostIndex, .offset = imm };
1041 return .{ .encoding = .post_index, .offset = imm };
10381042 }
10391043
10401044 pub fn pre_index(imm: i9) LoadStorePairOffset {
1041 return .{ .encoding = .PreIndex, .offset = imm };
1045 return .{ .encoding = .pre_index, .offset = imm };
10421046 }
10431047
10441048 pub fn signed(imm: i9) LoadStorePairOffset {
1045 return .{ .encoding = .Signed, .offset = imm };
1049 return .{ .encoding = .signed, .offset = imm };
10461050 }
10471051 };
10481052