authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-11-13 06:17:08-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-11-13 06:17:08-08:00
logd3a099c14fe9b7b575a0cd7bb9cd05b49625a71e
treea7ba0e0d9771c6a83493dd0feb931723a1ad2256
parent71388b980bfc4c7eb267ed7c168c2395098f6db2
parent96e715d5a3a5e75e691bedd6a2dcebffc09639bb
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #10142 from joachimschmidt557/stage2-aarch64

stage2 AArch64: fix loading/storing to/from stack

5 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();
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+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/// 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),
...@@ -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));
588597
589 // ldr reg, reg, offset598 // 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 }));
596604
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}
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;
...@@ -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 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
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 }
743743
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 size755 };
765 }
766 }756 }
767757
768 fn exceptionGeneration(758 fn exceptionGeneration(
...@@ -1001,43 +991,32 @@ pub const Instruction = union(enum) {...@@ -1001,43 +991,32 @@ pub const Instruction = union(enum) {
1001991
1002 // Load or store register992 // Load or store register
1003993
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 }
1018997
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 }
10221001
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 }
10261005
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 }
10301009
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 }
10341013
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 }
10381017
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 }
10421021
1043 // Load or store pair of registers1022 // 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], #-11313 .{ // 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, label1321 .{ // 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], #0xaa1325 .{ // 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, #0x81349 .{ // 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, literal2120 // 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 disp2125 // 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, offset2224 // 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 },