authorgravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2021-11-12 22:14:49+01:00
committergravatar for joachim.schmidt557@outlook.comJoachim Schmidt <joachim.schmidt557@outlook.com> 2021-11-12 22:23:31+01:00
log96e715d5a3a5e75e691bedd6a2dcebffc09639bb
treea7ba0e0d9771c6a83493dd0feb931723a1ad2256
parent8ab90a0b32834d28e08210d271522e58c2a931d7
signaturelock-open Commit is signed but in an unrecognized format.

stage2 AArch64: add new load/store from/to stack MIR instructions


3 files changed, 126 insertions(+), 39 deletions(-)

src/arch/aarch64/CodeGen.zig+24-38
......@@ -302,6 +302,7 @@ pub fn generate(
302302 .prev_di_pc = 0,
303303 .prev_di_line = module_fn.lbrace_line,
304304 .prev_di_column = module_fn.lbrace_column,
305 .stack_size = mem.alignForwardGeneric(u32, function.max_end_stack, function.stack_align),
305306 };
306307 defer emit.deinit();
307308
......@@ -1346,9 +1347,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
13461347 const stack_offset = try self.allocMem(inst, abi_size, abi_align);
13471348 try self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
13481349
1349 // TODO correct loading and storing from memory
1350 // break :blk MCValue{ .stack_offset = stack_offset };
1351 break :blk result;
1350 break :blk MCValue{ .stack_offset = stack_offset };
13521351 },
13531352 else => result,
13541353 };
......@@ -2261,28 +2260,23 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
22612260
22622261 switch (abi_size) {
22632262 1, 2, 4, 8 => {
2264 const offset = if (math.cast(i9, adj_off)) |imm|
2265 Instruction.LoadStoreOffset.imm_post_index(-imm)
2266 else |_|
2267 Instruction.LoadStoreOffset.reg(try self.copyToTmpRegister(Type.initTag(.u64), MCValue{ .immediate = adj_off }));
2268 const rn: Register = switch (self.target.cpu.arch) {
2269 .aarch64, .aarch64_be => .x29,
2270 .aarch64_32 => .w29,
2271 else => unreachable,
2272 };
22732263 const tag: Mir.Inst.Tag = switch (abi_size) {
2274 1 => .strb,
2275 2 => .strh,
2276 4, 8 => .str,
2264 1 => .strb_stack,
2265 2 => .strh_stack,
2266 4, 8 => .str_stack,
2267 else => unreachable, // unexpected abi size
2268 };
2269 const rt: Register = switch (abi_size) {
2270 1, 2, 4 => reg.to32(),
2271 8 => reg.to64(),
22772272 else => unreachable, // unexpected abi size
22782273 };
22792274
22802275 _ = try self.addInst(.{
22812276 .tag = tag,
2282 .data = .{ .load_store_register = .{
2283 .rt = reg,
2284 .rn = rn,
2285 .offset = offset,
2277 .data = .{ .load_store_stack = .{
2278 .rt = rt,
2279 .offset = @intCast(u32, adj_off),
22862280 } },
22872281 });
22882282 },
......@@ -2384,36 +2378,28 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
23842378 });
23852379 },
23862380 .stack_offset => |unadjusted_off| {
2387 // TODO: maybe addressing from sp instead of fp
23882381 const abi_size = ty.abiSize(self.target.*);
23892382 const adj_off = unadjusted_off + abi_size;
23902383
2391 const rn: Register = switch (self.target.cpu.arch) {
2392 .aarch64, .aarch64_be => .x29,
2393 .aarch64_32 => .w29,
2394 else => unreachable,
2395 };
2396
2397 const offset = if (math.cast(i9, adj_off)) |imm|
2398 Instruction.LoadStoreOffset.imm_post_index(-imm)
2399 else |_|
2400 Instruction.LoadStoreOffset.reg(try self.copyToTmpRegister(Type.initTag(.u64), MCValue{ .immediate = adj_off }));
2401
24022384 switch (abi_size) {
24032385 1, 2, 4, 8 => {
24042386 const tag: Mir.Inst.Tag = switch (abi_size) {
2405 1 => .ldrb,
2406 2 => .ldrh,
2407 4, 8 => .ldr,
2387 1 => .ldrb_stack,
2388 2 => .ldrh_stack,
2389 4, 8 => .ldr_stack,
2390 else => unreachable, // unexpected abi size
2391 };
2392 const rt: Register = switch (abi_size) {
2393 1, 2, 4 => reg.to32(),
2394 8 => reg.to64(),
24082395 else => unreachable, // unexpected abi size
24092396 };
24102397
24112398 _ = try self.addInst(.{
24122399 .tag = tag,
2413 .data = .{ .load_store_register = .{
2414 .rt = reg,
2415 .rn = rn,
2416 .offset = offset,
2400 .data = .{ .load_store_stack = .{
2401 .rt = rt,
2402 .offset = @intCast(u32, adj_off),
24172403 } },
24182404 });
24192405 },
src/arch/aarch64/Emit.zig+82
......@@ -42,6 +42,8 @@ branch_forward_origins: std.AutoHashMapUnmanaged(Mir.Inst.Index, std.ArrayListUn
4242/// instruction
4343code_offset_mapping: std.AutoHashMapUnmanaged(Mir.Inst.Index, usize) = .{},
4444
45stack_size: u32,
46
4547const InnerError = error{
4648 OutOfMemory,
4749 EmitFail,
......@@ -103,6 +105,13 @@ pub fn emitMir(
103105 .ldp => try emit.mirLoadStoreRegisterPair(inst),
104106 .stp => try emit.mirLoadStoreRegisterPair(inst),
105107
108 .ldr_stack => try emit.mirLoadStoreStack(inst),
109 .ldrb_stack => try emit.mirLoadStoreStack(inst),
110 .ldrh_stack => try emit.mirLoadStoreStack(inst),
111 .str_stack => try emit.mirLoadStoreStack(inst),
112 .strb_stack => try emit.mirLoadStoreStack(inst),
113 .strh_stack => try emit.mirLoadStoreStack(inst),
114
106115 .ldr => try emit.mirLoadStoreRegister(inst),
107116 .ldrb => try emit.mirLoadStoreRegister(inst),
108117 .ldrh => try emit.mirLoadStoreRegister(inst),
......@@ -652,6 +661,79 @@ fn mirLoadStoreRegisterPair(emit: *Emit, inst: Mir.Inst.Index) !void {
652661 }
653662}
654663
664fn mirLoadStoreStack(emit: *Emit, inst: Mir.Inst.Index) !void {
665 const tag = emit.mir.instructions.items(.tag)[inst];
666 const load_store_stack = emit.mir.instructions.items(.data)[inst].load_store_stack;
667
668 const raw_offset = emit.stack_size - load_store_stack.offset;
669 const offset = switch (tag) {
670 .ldrb_stack, .strb_stack => blk: {
671 if (math.cast(u12, raw_offset)) |imm| {
672 break :blk Instruction.LoadStoreOffset.imm(imm);
673 } else |_| {
674 return emit.fail("TODO load/store stack byte with larger offset", .{});
675 }
676 },
677 .ldrh_stack, .strh_stack => blk: {
678 assert(std.mem.isAlignedGeneric(u32, raw_offset, 2)); // misaligned stack entry
679 if (math.cast(u12, @divExact(raw_offset, 2))) |imm| {
680 break :blk Instruction.LoadStoreOffset.imm(imm);
681 } else |_| {
682 return emit.fail("TODO load/store stack halfword with larger offset", .{});
683 }
684 },
685 .ldr_stack, .str_stack => blk: {
686 const alignment: u32 = switch (load_store_stack.rt.size()) {
687 32 => 4,
688 64 => 8,
689 else => unreachable,
690 };
691
692 assert(std.mem.isAlignedGeneric(u32, raw_offset, alignment)); // misaligned stack entry
693 if (math.cast(u12, @divExact(raw_offset, alignment))) |imm| {
694 break :blk Instruction.LoadStoreOffset.imm(imm);
695 } else |_| {
696 return emit.fail("TODO load/store stack with larger offset", .{});
697 }
698 },
699 else => unreachable,
700 };
701
702 switch (tag) {
703 .ldr_stack => try emit.writeInstruction(Instruction.ldr(
704 load_store_stack.rt,
705 Register.sp,
706 offset,
707 )),
708 .ldrb_stack => try emit.writeInstruction(Instruction.ldrb(
709 load_store_stack.rt,
710 Register.sp,
711 offset,
712 )),
713 .ldrh_stack => try emit.writeInstruction(Instruction.ldrh(
714 load_store_stack.rt,
715 Register.sp,
716 offset,
717 )),
718 .str_stack => try emit.writeInstruction(Instruction.str(
719 load_store_stack.rt,
720 Register.sp,
721 offset,
722 )),
723 .strb_stack => try emit.writeInstruction(Instruction.strb(
724 load_store_stack.rt,
725 Register.sp,
726 offset,
727 )),
728 .strh_stack => try emit.writeInstruction(Instruction.strh(
729 load_store_stack.rt,
730 Register.sp,
731 offset,
732 )),
733 else => unreachable,
734 }
735}
736
655737fn mirLoadStoreRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
656738 const tag = emit.mir.instructions.items(.tag)[inst];
657739 const load_store_register = emit.mir.instructions.items(.data)[inst].load_store_register;
src/arch/aarch64/Mir.zig+20-1
......@@ -56,12 +56,18 @@ pub const Inst = struct {
5656 load_memory,
5757 /// Load Pair of Registers
5858 ldp,
59 /// Pseudo-instruction: Load from stack
60 ldr_stack,
5961 /// Load Register
6062 // TODO: split into ldr_immediate and ldr_register
6163 ldr,
64 /// Pseudo-instruction: Load byte from stack
65 ldrb_stack,
6266 /// Load Register Byte
6367 // TODO: split into ldrb_immediate and ldrb_register
6468 ldrb,
69 /// Pseudo-instruction: Load halfword from stack
70 ldrh_stack,
6571 /// Load Register Halfword
6672 // TODO: split into ldrh_immediate and ldrh_register
6773 ldrh,
......@@ -79,12 +85,18 @@ pub const Inst = struct {
7985 ret,
8086 /// Store Pair of Registers
8187 stp,
88 /// Pseudo-instruction: Store to stack
89 str_stack,
8290 /// Store Register
8391 // TODO: split into str_immediate and str_register
8492 str,
93 /// Pseudo-instruction: Store byte to stack
94 strb_stack,
8595 /// Store Register Byte
8696 // TODO: split into strb_immediate and strb_register
8797 strb,
98 /// Pseudo-instruction: Store halfword to stack
99 strh_stack,
88100 /// Store Register Halfword
89101 // TODO: split into strh_immediate and strh_register
90102 strh,
......@@ -175,7 +187,7 @@ pub const Inst = struct {
175187 rm: Register,
176188 cond: bits.Instruction.Condition,
177189 },
178 /// Three registers and a LoadStoreOffset
190 /// Two registers and a LoadStoreOffset
179191 ///
180192 /// Used by e.g. str_register
181193 load_store_register: struct {
......@@ -183,6 +195,13 @@ pub const Inst = struct {
183195 rn: Register,
184196 offset: bits.Instruction.LoadStoreOffset,
185197 },
198 /// A registers and a stack offset
199 ///
200 /// Used by e.g. str_register
201 load_store_stack: struct {
202 rt: Register,
203 offset: u32,
204 },
186205 /// Three registers and a LoadStorePairOffset
187206 ///
188207 /// Used by e.g. stp