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(...@@ -302,6 +302,7 @@ pub fn generate(
302 .prev_di_pc = 0,302 .prev_di_pc = 0,
303 .prev_di_line = module_fn.lbrace_line,303 .prev_di_line = module_fn.lbrace_line,
304 .prev_di_column = module_fn.lbrace_column,304 .prev_di_column = module_fn.lbrace_column,
305 .stack_size = mem.alignForwardGeneric(u32, function.max_end_stack, function.stack_align),
305 };306 };
306 defer emit.deinit();307 defer emit.deinit();
307308
...@@ -1346,9 +1347,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {...@@ -1346,9 +1347,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
1346 const stack_offset = try self.allocMem(inst, abi_size, abi_align);1347 const stack_offset = try self.allocMem(inst, abi_size, abi_align);
1347 try self.genSetStack(ty, stack_offset, MCValue{ .register = reg });1348 try self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
13481349
1349 // TODO correct loading and storing from memory1350 break :blk MCValue{ .stack_offset = stack_offset };
1350 // break :blk MCValue{ .stack_offset = stack_offset };
1351 break :blk result;
1352 },1351 },
1353 else => result,1352 else => result,
1354 };1353 };
...@@ -2261,28 +2260,23 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -2261,28 +2260,23 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
22612260
2262 switch (abi_size) {2261 switch (abi_size) {
2263 1, 2, 4, 8 => {2262 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 };
2273 const tag: Mir.Inst.Tag = switch (abi_size) {2263 const tag: Mir.Inst.Tag = switch (abi_size) {
2274 1 => .strb,2264 1 => .strb_stack,
2275 2 => .strh,2265 2 => .strh_stack,
2276 4, 8 => .str,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(),
2277 else => unreachable, // unexpected abi size2272 else => unreachable, // unexpected abi size
2278 };2273 };
22792274
2280 _ = try self.addInst(.{2275 _ = try self.addInst(.{
2281 .tag = tag,2276 .tag = tag,
2282 .data = .{ .load_store_register = .{2277 .data = .{ .load_store_stack = .{
2283 .rt = reg,2278 .rt = rt,
2284 .rn = rn,2279 .offset = @intCast(u32, adj_off),
2285 .offset = offset,
2286 } },2280 } },
2287 });2281 });
2288 },2282 },
...@@ -2384,36 +2378,28 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -2384,36 +2378,28 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
2384 });2378 });
2385 },2379 },
2386 .stack_offset => |unadjusted_off| {2380 .stack_offset => |unadjusted_off| {
2387 // TODO: maybe addressing from sp instead of fp
2388 const abi_size = ty.abiSize(self.target.*);2381 const abi_size = ty.abiSize(self.target.*);
2389 const adj_off = unadjusted_off + abi_size;2382 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
2402 switch (abi_size) {2384 switch (abi_size) {
2403 1, 2, 4, 8 => {2385 1, 2, 4, 8 => {
2404 const tag: Mir.Inst.Tag = switch (abi_size) {2386 const tag: Mir.Inst.Tag = switch (abi_size) {
2405 1 => .ldrb,2387 1 => .ldrb_stack,
2406 2 => .ldrh,2388 2 => .ldrh_stack,
2407 4, 8 => .ldr,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(),
2408 else => unreachable, // unexpected abi size2395 else => unreachable, // unexpected abi size
2409 };2396 };
24102397
2411 _ = try self.addInst(.{2398 _ = try self.addInst(.{
2412 .tag = tag,2399 .tag = tag,
2413 .data = .{ .load_store_register = .{2400 .data = .{ .load_store_stack = .{
2414 .rt = reg,2401 .rt = rt,
2415 .rn = rn,2402 .offset = @intCast(u32, adj_off),
2416 .offset = offset,
2417 } },2403 } },
2418 });2404 });
2419 },2405 },
src/arch/aarch64/Emit.zig+82
...@@ -42,6 +42,8 @@ branch_forward_origins: std.AutoHashMapUnmanaged(Mir.Inst.Index, std.ArrayListUn...@@ -42,6 +42,8 @@ branch_forward_origins: std.AutoHashMapUnmanaged(Mir.Inst.Index, std.ArrayListUn
42/// instruction42/// instruction
43code_offset_mapping: std.AutoHashMapUnmanaged(Mir.Inst.Index, usize) = .{},43code_offset_mapping: std.AutoHashMapUnmanaged(Mir.Inst.Index, usize) = .{},
4444
45stack_size: u32,
46
45const InnerError = error{47const InnerError = error{
46 OutOfMemory,48 OutOfMemory,
47 EmitFail,49 EmitFail,
...@@ -103,6 +105,13 @@ pub fn emitMir(...@@ -103,6 +105,13 @@ pub fn emitMir(
103 .ldp => try emit.mirLoadStoreRegisterPair(inst),105 .ldp => try emit.mirLoadStoreRegisterPair(inst),
104 .stp => try emit.mirLoadStoreRegisterPair(inst),106 .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
106 .ldr => try emit.mirLoadStoreRegister(inst),115 .ldr => try emit.mirLoadStoreRegister(inst),
107 .ldrb => try emit.mirLoadStoreRegister(inst),116 .ldrb => try emit.mirLoadStoreRegister(inst),
108 .ldrh => try emit.mirLoadStoreRegister(inst),117 .ldrh => try emit.mirLoadStoreRegister(inst),
...@@ -652,6 +661,79 @@ fn mirLoadStoreRegisterPair(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -652,6 +661,79 @@ fn mirLoadStoreRegisterPair(emit: *Emit, inst: Mir.Inst.Index) !void {
652 }661 }
653}662}
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
655fn mirLoadStoreRegister(emit: *Emit, inst: Mir.Inst.Index) !void {737fn mirLoadStoreRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
656 const tag = emit.mir.instructions.items(.tag)[inst];738 const tag = emit.mir.instructions.items(.tag)[inst];
657 const load_store_register = emit.mir.instructions.items(.data)[inst].load_store_register;739 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 {...@@ -56,12 +56,18 @@ pub const Inst = struct {
56 load_memory,56 load_memory,
57 /// Load Pair of Registers57 /// Load Pair of Registers
58 ldp,58 ldp,
59 /// Pseudo-instruction: Load from stack
60 ldr_stack,
59 /// Load Register61 /// Load Register
60 // TODO: split into ldr_immediate and ldr_register62 // TODO: split into ldr_immediate and ldr_register
61 ldr,63 ldr,
64 /// Pseudo-instruction: Load byte from stack
65 ldrb_stack,
62 /// Load Register Byte66 /// Load Register Byte
63 // TODO: split into ldrb_immediate and ldrb_register67 // TODO: split into ldrb_immediate and ldrb_register
64 ldrb,68 ldrb,
69 /// Pseudo-instruction: Load halfword from stack
70 ldrh_stack,
65 /// Load Register Halfword71 /// Load Register Halfword
66 // TODO: split into ldrh_immediate and ldrh_register72 // TODO: split into ldrh_immediate and ldrh_register
67 ldrh,73 ldrh,
...@@ -79,12 +85,18 @@ pub const Inst = struct {...@@ -79,12 +85,18 @@ pub const Inst = struct {
79 ret,85 ret,
80 /// Store Pair of Registers86 /// Store Pair of Registers
81 stp,87 stp,
88 /// Pseudo-instruction: Store to stack
89 str_stack,
82 /// Store Register90 /// Store Register
83 // TODO: split into str_immediate and str_register91 // TODO: split into str_immediate and str_register
84 str,92 str,
93 /// Pseudo-instruction: Store byte to stack
94 strb_stack,
85 /// Store Register Byte95 /// Store Register Byte
86 // TODO: split into strb_immediate and strb_register96 // TODO: split into strb_immediate and strb_register
87 strb,97 strb,
98 /// Pseudo-instruction: Store halfword to stack
99 strh_stack,
88 /// Store Register Halfword100 /// Store Register Halfword
89 // TODO: split into strh_immediate and strh_register101 // TODO: split into strh_immediate and strh_register
90 strh,102 strh,
...@@ -175,7 +187,7 @@ pub const Inst = struct {...@@ -175,7 +187,7 @@ pub const Inst = struct {
175 rm: Register,187 rm: Register,
176 cond: bits.Instruction.Condition,188 cond: bits.Instruction.Condition,
177 },189 },
178 /// Three registers and a LoadStoreOffset190 /// Two registers and a LoadStoreOffset
179 ///191 ///
180 /// Used by e.g. str_register192 /// Used by e.g. str_register
181 load_store_register: struct {193 load_store_register: struct {
...@@ -183,6 +195,13 @@ pub const Inst = struct {...@@ -183,6 +195,13 @@ pub const Inst = struct {
183 rn: Register,195 rn: Register,
184 offset: bits.Instruction.LoadStoreOffset,196 offset: bits.Instruction.LoadStoreOffset,
185 },197 },
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 },
186 /// Three registers and a LoadStorePairOffset205 /// Three registers and a LoadStorePairOffset
187 ///206 ///
188 /// Used by e.g. stp207 /// Used by e.g. stp