| author | |
| committer | |
| log | 96e715d5a3a5e75e691bedd6a2dcebffc09639bb |
| tree | a7ba0e0d9771c6a83493dd0feb931723a1ad2256 |
| parent | 8ab90a0b32834d28e08210d271522e58c2a931d7 |
| signature |
3 files changed, 126 insertions(+), 39 deletions(-)
src/arch/aarch64/CodeGen.zig+24-38| ... | ... | @@ -302,6 +302,7 @@ pub fn generate( |
| 302 | 302 | .prev_di_pc = 0, |
| 303 | 303 | .prev_di_line = module_fn.lbrace_line, |
| 304 | 304 | .prev_di_column = module_fn.lbrace_column, |
| 305 | .stack_size = mem.alignForwardGeneric(u32, function.max_end_stack, function.stack_align), | |
| 305 | 306 | }; |
| 306 | 307 | defer emit.deinit(); |
| 307 | 308 | |
| ... | ... | @@ -1346,9 +1347,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 1346 | 1347 | const stack_offset = try self.allocMem(inst, abi_size, abi_align); |
| 1347 | 1348 | try self.genSetStack(ty, stack_offset, MCValue{ .register = reg }); |
| 1348 | 1349 | |
| 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 }; | |
| 1352 | 1351 | }, |
| 1353 | 1352 | else => result, |
| 1354 | 1353 | }; |
| ... | ... | @@ -2261,28 +2260,23 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro |
| 2261 | 2260 | |
| 2262 | 2261 | switch (abi_size) { |
| 2263 | 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 | 2263 | 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(), | |
| 2277 | 2272 | else => unreachable, // unexpected abi size |
| 2278 | 2273 | }; |
| 2279 | 2274 | |
| 2280 | 2275 | _ = try self.addInst(.{ |
| 2281 | 2276 | .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), | |
| 2286 | 2280 | } }, |
| 2287 | 2281 | }); |
| 2288 | 2282 | }, |
| ... | ... | @@ -2384,36 +2378,28 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void |
| 2384 | 2378 | }); |
| 2385 | 2379 | }, |
| 2386 | 2380 | .stack_offset => |unadjusted_off| { |
| 2387 | // TODO: maybe addressing from sp instead of fp | |
| 2388 | 2381 | const abi_size = ty.abiSize(self.target.*); |
| 2389 | 2382 | const adj_off = unadjusted_off + abi_size; |
| 2390 | 2383 | |
| 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 | 2384 | switch (abi_size) { |
| 2403 | 2385 | 1, 2, 4, 8 => { |
| 2404 | 2386 | 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(), | |
| 2408 | 2395 | else => unreachable, // unexpected abi size |
| 2409 | 2396 | }; |
| 2410 | 2397 | |
| 2411 | 2398 | _ = try self.addInst(.{ |
| 2412 | 2399 | .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), | |
| 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 | 42 | /// instruction |
| 43 | 43 | code_offset_mapping: std.AutoHashMapUnmanaged(Mir.Inst.Index, usize) = .{}, |
| 44 | 44 | |
| 45 | stack_size: u32, | |
| 46 | ||
| 45 | 47 | const InnerError = error{ |
| 46 | 48 | OutOfMemory, |
| 47 | 49 | EmitFail, |
| ... | ... | @@ -103,6 +105,13 @@ pub fn emitMir( |
| 103 | 105 | .ldp => try emit.mirLoadStoreRegisterPair(inst), |
| 104 | 106 | .stp => try emit.mirLoadStoreRegisterPair(inst), |
| 105 | 107 | |
| 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 | 115 | .ldr => try emit.mirLoadStoreRegister(inst), |
| 107 | 116 | .ldrb => try emit.mirLoadStoreRegister(inst), |
| 108 | 117 | .ldrh => try emit.mirLoadStoreRegister(inst), |
| ... | ... | @@ -652,6 +661,79 @@ fn mirLoadStoreRegisterPair(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 652 | 661 | } |
| 653 | 662 | } |
| 654 | 663 | |
| 664 | fn 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 | ||
| 655 | 737 | fn mirLoadStoreRegister(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 656 | 738 | const tag = emit.mir.instructions.items(.tag)[inst]; |
| 657 | 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 | 56 | load_memory, |
| 57 | 57 | /// Load Pair of Registers |
| 58 | 58 | ldp, |
| 59 | /// Pseudo-instruction: Load from stack | |
| 60 | ldr_stack, | |
| 59 | 61 | /// Load Register |
| 60 | 62 | // TODO: split into ldr_immediate and ldr_register |
| 61 | 63 | ldr, |
| 64 | /// Pseudo-instruction: Load byte from stack | |
| 65 | ldrb_stack, | |
| 62 | 66 | /// Load Register Byte |
| 63 | 67 | // TODO: split into ldrb_immediate and ldrb_register |
| 64 | 68 | ldrb, |
| 69 | /// Pseudo-instruction: Load halfword from stack | |
| 70 | ldrh_stack, | |
| 65 | 71 | /// Load Register Halfword |
| 66 | 72 | // TODO: split into ldrh_immediate and ldrh_register |
| 67 | 73 | ldrh, |
| ... | ... | @@ -79,12 +85,18 @@ pub const Inst = struct { |
| 79 | 85 | ret, |
| 80 | 86 | /// Store Pair of Registers |
| 81 | 87 | stp, |
| 88 | /// Pseudo-instruction: Store to stack | |
| 89 | str_stack, | |
| 82 | 90 | /// Store Register |
| 83 | 91 | // TODO: split into str_immediate and str_register |
| 84 | 92 | str, |
| 93 | /// Pseudo-instruction: Store byte to stack | |
| 94 | strb_stack, | |
| 85 | 95 | /// Store Register Byte |
| 86 | 96 | // TODO: split into strb_immediate and strb_register |
| 87 | 97 | strb, |
| 98 | /// Pseudo-instruction: Store halfword to stack | |
| 99 | strh_stack, | |
| 88 | 100 | /// Store Register Halfword |
| 89 | 101 | // TODO: split into strh_immediate and strh_register |
| 90 | 102 | strh, |
| ... | ... | @@ -175,7 +187,7 @@ pub const Inst = struct { |
| 175 | 187 | rm: Register, |
| 176 | 188 | cond: bits.Instruction.Condition, |
| 177 | 189 | }, |
| 178 | /// Three registers and a LoadStoreOffset | |
| 190 | /// Two registers and a LoadStoreOffset | |
| 179 | 191 | /// |
| 180 | 192 | /// Used by e.g. str_register |
| 181 | 193 | load_store_register: struct { |
| ... | ... | @@ -183,6 +195,13 @@ pub const Inst = struct { |
| 183 | 195 | rn: Register, |
| 184 | 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 | 205 | /// Three registers and a LoadStorePairOffset |
| 187 | 206 | /// |
| 188 | 207 | /// Used by e.g. stp |