| author | |
| committer | |
| log | d3a099c14fe9b7b575a0cd7bb9cd05b49625a71e |
| tree | a7ba0e0d9771c6a83493dd0feb931723a1ad2256 |
| parent | 71388b980bfc4c7eb267ed7c168c2395098f6db2 |
| parent | 96e715d5a3a5e75e691bedd6a2dcebffc09639bb |
| signature |
stage2 AArch64: fix loading/storing to/from stack5 files changed, 190 insertions(+), 124 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(); |
| 307 | 308 | ||
| ... | @@ -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 }); |
| 1348 | 1349 | ||
| 1349 | // TODO correct loading and storing from memory | 1350 | 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 |
| 2261 | 2260 | ||
| 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 size | 2272 | else => unreachable, // unexpected abi size |
| 2278 | }; | 2273 | }; |
| 2279 | 2274 | ||
| 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; |
| 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 | 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 size | 2395 | else => unreachable, // unexpected abi size |
| 2409 | }; | 2396 | }; |
| 2410 | 2397 | ||
| 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+96-13| ... | @@ -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 | /// instruction | 42 | /// instruction |
| 43 | code_offset_mapping: std.AutoHashMapUnmanaged(Mir.Inst.Index, usize) = .{}, | 43 | code_offset_mapping: std.AutoHashMapUnmanaged(Mir.Inst.Index, usize) = .{}, |
| 44 | 44 | ||
| 45 | stack_size: u32, | ||
| 46 | |||
| 45 | const InnerError = error{ | 47 | const 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), |
| 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 | .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), |
| ... | @@ -587,12 +596,11 @@ fn mirLoadMemory(emit: *Emit, inst: Mir.Inst.Index) !void { | ... | @@ -587,12 +596,11 @@ fn mirLoadMemory(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 587 | try emit.writeInstruction(Instruction.adrp(reg, 0)); | 596 | try emit.writeInstruction(Instruction.adrp(reg, 0)); |
| 588 | 597 | ||
| 589 | // ldr reg, reg, offset | 598 | // ldr reg, reg, offset |
| 590 | try emit.writeInstruction(Instruction.ldr(reg, .{ | 599 | try emit.writeInstruction(Instruction.ldr( |
| 591 | .register = .{ | 600 | reg, |
| 592 | .rn = reg, | 601 | reg, |
| 593 | .offset = Instruction.LoadStoreOffset.imm(0), | 602 | Instruction.LoadStoreOffset.imm(0), |
| 594 | }, | 603 | )); |
| 595 | })); | ||
| 596 | 604 | ||
| 597 | if (emit.bin_file.cast(link.File.MachO)) |macho_file| { | 605 | if (emit.bin_file.cast(link.File.MachO)) |macho_file| { |
| 598 | // TODO I think the reloc might be in the wrong place. | 606 | // TODO I think the reloc might be in the wrong place. |
| ... | @@ -626,7 +634,8 @@ fn mirLoadMemory(emit: *Emit, inst: Mir.Inst.Index) !void { | ... | @@ -626,7 +634,8 @@ fn mirLoadMemory(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 626 | try emit.moveImmediate(reg, addr); | 634 | try emit.moveImmediate(reg, addr); |
| 627 | try emit.writeInstruction(Instruction.ldr( | 635 | try emit.writeInstruction(Instruction.ldr( |
| 628 | reg, | 636 | reg, |
| 629 | .{ .register = .{ .rn = reg, .offset = Instruction.LoadStoreOffset.none } }, | 637 | reg, |
| 638 | Instruction.LoadStoreOffset.none, | ||
| 630 | )); | 639 | )); |
| 631 | } | 640 | } |
| 632 | } | 641 | } |
| ... | @@ -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 | } |
| 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 | fn mirLoadStoreRegister(emit: *Emit, inst: Mir.Inst.Index) !void { | 737 | fn 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; |
| ... | @@ -659,32 +741,33 @@ fn mirLoadStoreRegister(emit: *Emit, inst: Mir.Inst.Index) !void { | ... | @@ -659,32 +741,33 @@ fn mirLoadStoreRegister(emit: *Emit, inst: Mir.Inst.Index) !void { |
| 659 | switch (tag) { | 741 | switch (tag) { |
| 660 | .ldr => try emit.writeInstruction(Instruction.ldr( | 742 | .ldr => try emit.writeInstruction(Instruction.ldr( |
| 661 | load_store_register.rt, | 743 | load_store_register.rt, |
| 662 | .{ .register = .{ .rn = load_store_register.rn, .offset = load_store_register.offset } }, | 744 | load_store_register.rn, |
| 745 | load_store_register.offset, | ||
| 663 | )), | 746 | )), |
| 664 | .ldrb => try emit.writeInstruction(Instruction.ldrb( | 747 | .ldrb => try emit.writeInstruction(Instruction.ldrb( |
| 665 | load_store_register.rt, | 748 | load_store_register.rt, |
| 666 | load_store_register.rn, | 749 | load_store_register.rn, |
| 667 | .{ .offset = load_store_register.offset }, | 750 | load_store_register.offset, |
| 668 | )), | 751 | )), |
| 669 | .ldrh => try emit.writeInstruction(Instruction.ldrh( | 752 | .ldrh => try emit.writeInstruction(Instruction.ldrh( |
| 670 | load_store_register.rt, | 753 | load_store_register.rt, |
| 671 | load_store_register.rn, | 754 | load_store_register.rn, |
| 672 | .{ .offset = load_store_register.offset }, | 755 | load_store_register.offset, |
| 673 | )), | 756 | )), |
| 674 | .str => try emit.writeInstruction(Instruction.str( | 757 | .str => try emit.writeInstruction(Instruction.str( |
| 675 | load_store_register.rt, | 758 | load_store_register.rt, |
| 676 | load_store_register.rn, | 759 | load_store_register.rn, |
| 677 | .{ .offset = load_store_register.offset }, | 760 | load_store_register.offset, |
| 678 | )), | 761 | )), |
| 679 | .strb => try emit.writeInstruction(Instruction.strb( | 762 | .strb => try emit.writeInstruction(Instruction.strb( |
| 680 | load_store_register.rt, | 763 | load_store_register.rt, |
| 681 | load_store_register.rn, | 764 | load_store_register.rn, |
| 682 | .{ .offset = load_store_register.offset }, | 765 | load_store_register.offset, |
| 683 | )), | 766 | )), |
| 684 | .strh => try emit.writeInstruction(Instruction.strh( | 767 | .strh => try emit.writeInstruction(Instruction.strh( |
| 685 | load_store_register.rt, | 768 | load_store_register.rt, |
| 686 | load_store_register.rn, | 769 | load_store_register.rn, |
| 687 | .{ .offset = load_store_register.offset }, | 770 | load_store_register.offset, |
| 688 | )), | 771 | )), |
| 689 | else => unreachable, | 772 | else => unreachable, |
| 690 | } | 773 | } |
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 Registers | 57 | /// Load Pair of Registers |
| 58 | ldp, | 58 | ldp, |
| 59 | /// Pseudo-instruction: Load from stack | ||
| 60 | ldr_stack, | ||
| 59 | /// Load Register | 61 | /// Load Register |
| 60 | // TODO: split into ldr_immediate and ldr_register | 62 | // 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 Byte | 66 | /// Load Register Byte |
| 63 | // TODO: split into ldrb_immediate and ldrb_register | 67 | // 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 Halfword | 71 | /// Load Register Halfword |
| 66 | // TODO: split into ldrh_immediate and ldrh_register | 72 | // 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 Registers | 86 | /// Store Pair of Registers |
| 81 | stp, | 87 | stp, |
| 88 | /// Pseudo-instruction: Store to stack | ||
| 89 | str_stack, | ||
| 82 | /// Store Register | 90 | /// Store Register |
| 83 | // TODO: split into str_immediate and str_register | 91 | // 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 Byte | 95 | /// Store Register Byte |
| 86 | // TODO: split into strb_immediate and strb_register | 96 | // 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 Halfword | 100 | /// Store Register Halfword |
| 89 | // TODO: split into strh_immediate and strh_register | 101 | // 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 LoadStoreOffset | 190 | /// Two registers and a LoadStoreOffset |
| 179 | /// | 191 | /// |
| 180 | /// Used by e.g. str_register | 192 | /// 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 LoadStorePairOffset | 205 | /// Three registers and a LoadStorePairOffset |
| 187 | /// | 206 | /// |
| 188 | /// Used by e.g. stp | 207 | /// Used by e.g. stp |
src/arch/aarch64/bits.zig+36-57| ... | @@ -742,27 +742,17 @@ pub const Instruction = union(enum) { | ... | @@ -742,27 +742,17 @@ pub const Instruction = union(enum) { |
| 742 | } | 742 | } |
| 743 | 743 | ||
| 744 | fn loadLiteral(rt: Register, imm19: u19) Instruction { | 744 | fn loadLiteral(rt: Register, imm19: u19) Instruction { |
| 745 | switch (rt.size()) { | 745 | return Instruction{ |
| 746 | 32 => { | 746 | .load_literal = .{ |
| 747 | return Instruction{ | 747 | .rt = rt.id(), |
| 748 | .load_literal = .{ | 748 | .imm19 = imm19, |
| 749 | .rt = rt.id(), | 749 | .opc = switch (rt.size()) { |
| 750 | .imm19 = imm19, | 750 | 32 => 0b00, |
| 751 | .opc = 0b00, | 751 | 64 => 0b01, |
| 752 | }, | 752 | else => unreachable, // unexpected register size |
| 753 | }; | 753 | }, |
| 754 | }, | ||
| 755 | 64 => { | ||
| 756 | return Instruction{ | ||
| 757 | .load_literal = .{ | ||
| 758 | .rt = rt.id(), | ||
| 759 | .imm19 = imm19, | ||
| 760 | .opc = 0b01, | ||
| 761 | }, | ||
| 762 | }; | ||
| 763 | }, | 754 | }, |
| 764 | else => unreachable, // unexpected register size | 755 | }; |
| 765 | } | ||
| 766 | } | 756 | } |
| 767 | 757 | ||
| 768 | fn exceptionGeneration( | 758 | fn exceptionGeneration( |
| ... | @@ -1001,43 +991,32 @@ pub const Instruction = union(enum) { | ... | @@ -1001,43 +991,32 @@ pub const Instruction = union(enum) { |
| 1001 | 991 | ||
| 1002 | // Load or store register | 992 | // Load or store register |
| 1003 | 993 | ||
| 1004 | pub const LdrArgs = union(enum) { | 994 | pub fn ldrLiteral(rt: Register, literal: u19) Instruction { |
| 1005 | register: struct { | 995 | return loadLiteral(rt, literal); |
| 1006 | rn: Register, | ||
| 1007 | offset: LoadStoreOffset = LoadStoreOffset.none, | ||
| 1008 | }, | ||
| 1009 | literal: u19, | ||
| 1010 | }; | ||
| 1011 | |||
| 1012 | pub fn ldr(rt: Register, args: LdrArgs) Instruction { | ||
| 1013 | switch (args) { | ||
| 1014 | .register => |info| return loadStoreRegister(rt, info.rn, info.offset, .ldr), | ||
| 1015 | .literal => |literal| return loadLiteral(rt, literal), | ||
| 1016 | } | ||
| 1017 | } | 996 | } |
| 1018 | 997 | ||
| 1019 | pub fn ldrh(rt: Register, rn: Register, args: StrArgs) Instruction { | 998 | pub fn ldr(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction { |
| 1020 | return loadStoreRegister(rt, rn, args.offset, .ldrh); | 999 | return loadStoreRegister(rt, rn, offset, .ldr); |
| 1021 | } | 1000 | } |
| 1022 | 1001 | ||
| 1023 | pub fn ldrb(rt: Register, rn: Register, args: StrArgs) Instruction { | 1002 | pub fn ldrh(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction { |
| 1024 | return loadStoreRegister(rt, rn, args.offset, .ldrb); | 1003 | return loadStoreRegister(rt, rn, offset, .ldrh); |
| 1025 | } | 1004 | } |
| 1026 | 1005 | ||
| 1027 | pub const StrArgs = struct { | 1006 | pub fn ldrb(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction { |
| 1028 | offset: LoadStoreOffset = LoadStoreOffset.none, | 1007 | return loadStoreRegister(rt, rn, offset, .ldrb); |
| 1029 | }; | 1008 | } |
| 1030 | 1009 | ||
| 1031 | pub fn str(rt: Register, rn: Register, args: StrArgs) Instruction { | 1010 | pub fn str(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction { |
| 1032 | return loadStoreRegister(rt, rn, args.offset, .str); | 1011 | return loadStoreRegister(rt, rn, offset, .str); |
| 1033 | } | 1012 | } |
| 1034 | 1013 | ||
| 1035 | pub fn strh(rt: Register, rn: Register, args: StrArgs) Instruction { | 1014 | pub fn strh(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction { |
| 1036 | return loadStoreRegister(rt, rn, args.offset, .strh); | 1015 | return loadStoreRegister(rt, rn, offset, .strh); |
| 1037 | } | 1016 | } |
| 1038 | 1017 | ||
| 1039 | pub fn strb(rt: Register, rn: Register, args: StrArgs) Instruction { | 1018 | pub fn strb(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction { |
| 1040 | return loadStoreRegister(rt, rn, args.offset, .strb); | 1019 | return loadStoreRegister(rt, rn, offset, .strb); |
| 1041 | } | 1020 | } |
| 1042 | 1021 | ||
| 1043 | // Load or store pair of registers | 1022 | // Load or store pair of registers |
| ... | @@ -1324,47 +1303,47 @@ test "serialize instructions" { | ... | @@ -1324,47 +1303,47 @@ test "serialize instructions" { |
| 1324 | .expected = 0b1_00101_00_0000_0000_0000_0000_0000_0100, | 1303 | .expected = 0b1_00101_00_0000_0000_0000_0000_0000_0100, |
| 1325 | }, | 1304 | }, |
| 1326 | .{ // ldr x2, [x1] | 1305 | .{ // ldr x2, [x1] |
| 1327 | .inst = Instruction.ldr(.x2, .{ .register = .{ .rn = .x1 } }), | 1306 | .inst = Instruction.ldr(.x2, .x1, Instruction.LoadStoreOffset.none), |
| 1328 | .expected = 0b11_111_0_01_01_000000000000_00001_00010, | 1307 | .expected = 0b11_111_0_01_01_000000000000_00001_00010, |
| 1329 | }, | 1308 | }, |
| 1330 | .{ // ldr x2, [x1, #1]! | 1309 | .{ // ldr x2, [x1, #1]! |
| 1331 | .inst = Instruction.ldr(.x2, .{ .register = .{ .rn = .x1, .offset = Instruction.LoadStoreOffset.imm_pre_index(1) } }), | 1310 | .inst = Instruction.ldr(.x2, .x1, Instruction.LoadStoreOffset.imm_pre_index(1)), |
| 1332 | .expected = 0b11_111_0_00_01_0_000000001_11_00001_00010, | 1311 | .expected = 0b11_111_0_00_01_0_000000001_11_00001_00010, |
| 1333 | }, | 1312 | }, |
| 1334 | .{ // ldr x2, [x1], #-1 | 1313 | .{ // ldr x2, [x1], #-1 |
| 1335 | .inst = Instruction.ldr(.x2, .{ .register = .{ .rn = .x1, .offset = Instruction.LoadStoreOffset.imm_post_index(-1) } }), | 1314 | .inst = Instruction.ldr(.x2, .x1, Instruction.LoadStoreOffset.imm_post_index(-1)), |
| 1336 | .expected = 0b11_111_0_00_01_0_111111111_01_00001_00010, | 1315 | .expected = 0b11_111_0_00_01_0_111111111_01_00001_00010, |
| 1337 | }, | 1316 | }, |
| 1338 | .{ // ldr x2, [x1], (x3) | 1317 | .{ // ldr x2, [x1], (x3) |
| 1339 | .inst = Instruction.ldr(.x2, .{ .register = .{ .rn = .x1, .offset = Instruction.LoadStoreOffset.reg(.x3) } }), | 1318 | .inst = Instruction.ldr(.x2, .x1, Instruction.LoadStoreOffset.reg(.x3)), |
| 1340 | .expected = 0b11_111_0_00_01_1_00011_011_0_10_00001_00010, | 1319 | .expected = 0b11_111_0_00_01_1_00011_011_0_10_00001_00010, |
| 1341 | }, | 1320 | }, |
| 1342 | .{ // ldr x2, label | 1321 | .{ // ldr x2, label |
| 1343 | .inst = Instruction.ldr(.x2, .{ .literal = 0x1 }), | 1322 | .inst = Instruction.ldrLiteral(.x2, 0x1), |
| 1344 | .expected = 0b01_011_0_00_0000000000000000001_00010, | 1323 | .expected = 0b01_011_0_00_0000000000000000001_00010, |
| 1345 | }, | 1324 | }, |
| 1346 | .{ // ldrh x7, [x4], #0xaa | 1325 | .{ // ldrh x7, [x4], #0xaa |
| 1347 | .inst = Instruction.ldrh(.x7, .x4, .{ .offset = Instruction.LoadStoreOffset.imm_post_index(0xaa) }), | 1326 | .inst = Instruction.ldrh(.x7, .x4, Instruction.LoadStoreOffset.imm_post_index(0xaa)), |
| 1348 | .expected = 0b01_111_0_00_01_0_010101010_01_00100_00111, | 1327 | .expected = 0b01_111_0_00_01_0_010101010_01_00100_00111, |
| 1349 | }, | 1328 | }, |
| 1350 | .{ // ldrb x9, [x15, #0xff]! | 1329 | .{ // ldrb x9, [x15, #0xff]! |
| 1351 | .inst = Instruction.ldrb(.x9, .x15, .{ .offset = Instruction.LoadStoreOffset.imm_pre_index(0xff) }), | 1330 | .inst = Instruction.ldrb(.x9, .x15, Instruction.LoadStoreOffset.imm_pre_index(0xff)), |
| 1352 | .expected = 0b00_111_0_00_01_0_011111111_11_01111_01001, | 1331 | .expected = 0b00_111_0_00_01_0_011111111_11_01111_01001, |
| 1353 | }, | 1332 | }, |
| 1354 | .{ // str x2, [x1] | 1333 | .{ // str x2, [x1] |
| 1355 | .inst = Instruction.str(.x2, .x1, .{}), | 1334 | .inst = Instruction.str(.x2, .x1, Instruction.LoadStoreOffset.none), |
| 1356 | .expected = 0b11_111_0_01_00_000000000000_00001_00010, | 1335 | .expected = 0b11_111_0_01_00_000000000000_00001_00010, |
| 1357 | }, | 1336 | }, |
| 1358 | .{ // str x2, [x1], (x3) | 1337 | .{ // str x2, [x1], (x3) |
| 1359 | .inst = Instruction.str(.x2, .x1, .{ .offset = Instruction.LoadStoreOffset.reg(.x3) }), | 1338 | .inst = Instruction.str(.x2, .x1, Instruction.LoadStoreOffset.reg(.x3)), |
| 1360 | .expected = 0b11_111_0_00_00_1_00011_011_0_10_00001_00010, | 1339 | .expected = 0b11_111_0_00_00_1_00011_011_0_10_00001_00010, |
| 1361 | }, | 1340 | }, |
| 1362 | .{ // strh w0, [x1] | 1341 | .{ // strh w0, [x1] |
| 1363 | .inst = Instruction.strh(.w0, .x1, .{}), | 1342 | .inst = Instruction.strh(.w0, .x1, Instruction.LoadStoreOffset.none), |
| 1364 | .expected = 0b01_111_0_01_00_000000000000_00001_00000, | 1343 | .expected = 0b01_111_0_01_00_000000000000_00001_00000, |
| 1365 | }, | 1344 | }, |
| 1366 | .{ // strb w8, [x9] | 1345 | .{ // strb w8, [x9] |
| 1367 | .inst = Instruction.strb(.w8, .x9, .{}), | 1346 | .inst = Instruction.strb(.w8, .x9, Instruction.LoadStoreOffset.none), |
| 1368 | .expected = 0b00_111_0_01_00_000000000000_01001_01000, | 1347 | .expected = 0b00_111_0_01_00_000000000000_01001_01000, |
| 1369 | }, | 1348 | }, |
| 1370 | .{ // adr x2, #0x8 | 1349 | .{ // adr x2, #0x8 |
src/link/MachO.zig+14-15| ... | @@ -2041,12 +2041,11 @@ fn createStubHelperPreambleAtom(self: *MachO) !void { | ... | @@ -2041,12 +2041,11 @@ fn createStubHelperPreambleAtom(self: *MachO) !void { |
| 2041 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGE21), | 2041 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGE21), |
| 2042 | }); | 2042 | }); |
| 2043 | // ldr x16, [x16, 0] | 2043 | // ldr x16, [x16, 0] |
| 2044 | mem.writeIntLittle(u32, atom.code.items[16..][0..4], aarch64.Instruction.ldr(.x16, .{ | 2044 | mem.writeIntLittle(u32, atom.code.items[16..][0..4], aarch64.Instruction.ldr( |
| 2045 | .register = .{ | 2045 | .x16, |
| 2046 | .rn = .x16, | 2046 | .x16, |
| 2047 | .offset = aarch64.Instruction.LoadStoreOffset.imm(0), | 2047 | aarch64.Instruction.LoadStoreOffset.imm(0), |
| 2048 | }, | 2048 | ).toU32()); |
| 2049 | }).toU32()); | ||
| 2050 | atom.relocs.appendAssumeCapacity(.{ | 2049 | atom.relocs.appendAssumeCapacity(.{ |
| 2051 | .offset = 16, | 2050 | .offset = 16, |
| 2052 | .target = .{ .global = self.undefs.items[self.dyld_stub_binder_index.?].n_strx }, | 2051 | .target = .{ .global = self.undefs.items[self.dyld_stub_binder_index.?].n_strx }, |
| ... | @@ -2119,9 +2118,10 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom { | ... | @@ -2119,9 +2118,10 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom { |
| 2119 | break :blk try math.cast(u18, div_res); | 2118 | break :blk try math.cast(u18, div_res); |
| 2120 | }; | 2119 | }; |
| 2121 | // ldr w16, literal | 2120 | // ldr w16, literal |
| 2122 | mem.writeIntLittle(u32, atom.code.items[0..4], aarch64.Instruction.ldr(.w16, .{ | 2121 | mem.writeIntLittle(u32, atom.code.items[0..4], aarch64.Instruction.ldrLiteral( |
| 2123 | .literal = literal, | 2122 | .w16, |
| 2124 | }).toU32()); | 2123 | literal, |
| 2124 | ).toU32()); | ||
| 2125 | // b disp | 2125 | // b disp |
| 2126 | mem.writeIntLittle(u32, atom.code.items[4..8], aarch64.Instruction.b(0).toU32()); | 2126 | mem.writeIntLittle(u32, atom.code.items[4..8], aarch64.Instruction.b(0).toU32()); |
| 2127 | atom.relocs.appendAssumeCapacity(.{ | 2127 | atom.relocs.appendAssumeCapacity(.{ |
| ... | @@ -2222,12 +2222,11 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom { | ... | @@ -2222,12 +2222,11 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom { |
| 2222 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGE21), | 2222 | .@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGE21), |
| 2223 | }); | 2223 | }); |
| 2224 | // ldr x16, x16, offset | 2224 | // ldr x16, x16, offset |
| 2225 | mem.writeIntLittle(u32, atom.code.items[4..8], aarch64.Instruction.ldr(.x16, .{ | 2225 | mem.writeIntLittle(u32, atom.code.items[4..8], aarch64.Instruction.ldr( |
| 2226 | .register = .{ | 2226 | .x16, |
| 2227 | .rn = .x16, | 2227 | .x16, |
| 2228 | .offset = aarch64.Instruction.LoadStoreOffset.imm(0), | 2228 | aarch64.Instruction.LoadStoreOffset.imm(0), |
| 2229 | }, | 2229 | ).toU32()); |
| 2230 | }).toU32()); | ||
| 2231 | atom.relocs.appendAssumeCapacity(.{ | 2230 | atom.relocs.appendAssumeCapacity(.{ |
| 2232 | .offset = 4, | 2231 | .offset = 4, |
| 2233 | .target = .{ .local = laptr_sym_index }, | 2232 | .target = .{ .local = laptr_sym_index }, |