Merge pull request #10142 from joachimschmidt557/stage2-aarch64
stage2 AArch64: fix loading/storing to/from stack
This commit is contained in:
@@ -302,6 +302,7 @@ pub fn generate(
|
||||
.prev_di_pc = 0,
|
||||
.prev_di_line = module_fn.lbrace_line,
|
||||
.prev_di_column = module_fn.lbrace_column,
|
||||
.stack_size = mem.alignForwardGeneric(u32, function.max_end_stack, function.stack_align),
|
||||
};
|
||||
defer emit.deinit();
|
||||
|
||||
@@ -1346,9 +1347,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const stack_offset = try self.allocMem(inst, abi_size, abi_align);
|
||||
try self.genSetStack(ty, stack_offset, MCValue{ .register = reg });
|
||||
|
||||
// TODO correct loading and storing from memory
|
||||
// break :blk MCValue{ .stack_offset = stack_offset };
|
||||
break :blk result;
|
||||
break :blk MCValue{ .stack_offset = stack_offset };
|
||||
},
|
||||
else => result,
|
||||
};
|
||||
@@ -2261,28 +2260,23 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
|
||||
|
||||
switch (abi_size) {
|
||||
1, 2, 4, 8 => {
|
||||
const offset = if (math.cast(i9, adj_off)) |imm|
|
||||
Instruction.LoadStoreOffset.imm_post_index(-imm)
|
||||
else |_|
|
||||
Instruction.LoadStoreOffset.reg(try self.copyToTmpRegister(Type.initTag(.u64), MCValue{ .immediate = adj_off }));
|
||||
const rn: Register = switch (self.target.cpu.arch) {
|
||||
.aarch64, .aarch64_be => .x29,
|
||||
.aarch64_32 => .w29,
|
||||
else => unreachable,
|
||||
};
|
||||
const tag: Mir.Inst.Tag = switch (abi_size) {
|
||||
1 => .strb,
|
||||
2 => .strh,
|
||||
4, 8 => .str,
|
||||
1 => .strb_stack,
|
||||
2 => .strh_stack,
|
||||
4, 8 => .str_stack,
|
||||
else => unreachable, // unexpected abi size
|
||||
};
|
||||
const rt: Register = switch (abi_size) {
|
||||
1, 2, 4 => reg.to32(),
|
||||
8 => reg.to64(),
|
||||
else => unreachable, // unexpected abi size
|
||||
};
|
||||
|
||||
_ = try self.addInst(.{
|
||||
.tag = tag,
|
||||
.data = .{ .load_store_register = .{
|
||||
.rt = reg,
|
||||
.rn = rn,
|
||||
.offset = offset,
|
||||
.data = .{ .load_store_stack = .{
|
||||
.rt = rt,
|
||||
.offset = @intCast(u32, adj_off),
|
||||
} },
|
||||
});
|
||||
},
|
||||
@@ -2384,36 +2378,28 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
|
||||
});
|
||||
},
|
||||
.stack_offset => |unadjusted_off| {
|
||||
// TODO: maybe addressing from sp instead of fp
|
||||
const abi_size = ty.abiSize(self.target.*);
|
||||
const adj_off = unadjusted_off + abi_size;
|
||||
|
||||
const rn: Register = switch (self.target.cpu.arch) {
|
||||
.aarch64, .aarch64_be => .x29,
|
||||
.aarch64_32 => .w29,
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
const offset = if (math.cast(i9, adj_off)) |imm|
|
||||
Instruction.LoadStoreOffset.imm_post_index(-imm)
|
||||
else |_|
|
||||
Instruction.LoadStoreOffset.reg(try self.copyToTmpRegister(Type.initTag(.u64), MCValue{ .immediate = adj_off }));
|
||||
|
||||
switch (abi_size) {
|
||||
1, 2, 4, 8 => {
|
||||
const tag: Mir.Inst.Tag = switch (abi_size) {
|
||||
1 => .ldrb,
|
||||
2 => .ldrh,
|
||||
4, 8 => .ldr,
|
||||
1 => .ldrb_stack,
|
||||
2 => .ldrh_stack,
|
||||
4, 8 => .ldr_stack,
|
||||
else => unreachable, // unexpected abi size
|
||||
};
|
||||
const rt: Register = switch (abi_size) {
|
||||
1, 2, 4 => reg.to32(),
|
||||
8 => reg.to64(),
|
||||
else => unreachable, // unexpected abi size
|
||||
};
|
||||
|
||||
_ = try self.addInst(.{
|
||||
.tag = tag,
|
||||
.data = .{ .load_store_register = .{
|
||||
.rt = reg,
|
||||
.rn = rn,
|
||||
.offset = offset,
|
||||
.data = .{ .load_store_stack = .{
|
||||
.rt = rt,
|
||||
.offset = @intCast(u32, adj_off),
|
||||
} },
|
||||
});
|
||||
},
|
||||
|
||||
@@ -42,6 +42,8 @@ branch_forward_origins: std.AutoHashMapUnmanaged(Mir.Inst.Index, std.ArrayListUn
|
||||
/// instruction
|
||||
code_offset_mapping: std.AutoHashMapUnmanaged(Mir.Inst.Index, usize) = .{},
|
||||
|
||||
stack_size: u32,
|
||||
|
||||
const InnerError = error{
|
||||
OutOfMemory,
|
||||
EmitFail,
|
||||
@@ -103,6 +105,13 @@ pub fn emitMir(
|
||||
.ldp => try emit.mirLoadStoreRegisterPair(inst),
|
||||
.stp => try emit.mirLoadStoreRegisterPair(inst),
|
||||
|
||||
.ldr_stack => try emit.mirLoadStoreStack(inst),
|
||||
.ldrb_stack => try emit.mirLoadStoreStack(inst),
|
||||
.ldrh_stack => try emit.mirLoadStoreStack(inst),
|
||||
.str_stack => try emit.mirLoadStoreStack(inst),
|
||||
.strb_stack => try emit.mirLoadStoreStack(inst),
|
||||
.strh_stack => try emit.mirLoadStoreStack(inst),
|
||||
|
||||
.ldr => try emit.mirLoadStoreRegister(inst),
|
||||
.ldrb => try emit.mirLoadStoreRegister(inst),
|
||||
.ldrh => try emit.mirLoadStoreRegister(inst),
|
||||
@@ -587,12 +596,11 @@ fn mirLoadMemory(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||
try emit.writeInstruction(Instruction.adrp(reg, 0));
|
||||
|
||||
// ldr reg, reg, offset
|
||||
try emit.writeInstruction(Instruction.ldr(reg, .{
|
||||
.register = .{
|
||||
.rn = reg,
|
||||
.offset = Instruction.LoadStoreOffset.imm(0),
|
||||
},
|
||||
}));
|
||||
try emit.writeInstruction(Instruction.ldr(
|
||||
reg,
|
||||
reg,
|
||||
Instruction.LoadStoreOffset.imm(0),
|
||||
));
|
||||
|
||||
if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
// TODO I think the reloc might be in the wrong place.
|
||||
@@ -626,7 +634,8 @@ fn mirLoadMemory(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||
try emit.moveImmediate(reg, addr);
|
||||
try emit.writeInstruction(Instruction.ldr(
|
||||
reg,
|
||||
.{ .register = .{ .rn = reg, .offset = Instruction.LoadStoreOffset.none } },
|
||||
reg,
|
||||
Instruction.LoadStoreOffset.none,
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -652,6 +661,79 @@ fn mirLoadStoreRegisterPair(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||
}
|
||||
}
|
||||
|
||||
fn mirLoadStoreStack(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||
const tag = emit.mir.instructions.items(.tag)[inst];
|
||||
const load_store_stack = emit.mir.instructions.items(.data)[inst].load_store_stack;
|
||||
|
||||
const raw_offset = emit.stack_size - load_store_stack.offset;
|
||||
const offset = switch (tag) {
|
||||
.ldrb_stack, .strb_stack => blk: {
|
||||
if (math.cast(u12, raw_offset)) |imm| {
|
||||
break :blk Instruction.LoadStoreOffset.imm(imm);
|
||||
} else |_| {
|
||||
return emit.fail("TODO load/store stack byte with larger offset", .{});
|
||||
}
|
||||
},
|
||||
.ldrh_stack, .strh_stack => blk: {
|
||||
assert(std.mem.isAlignedGeneric(u32, raw_offset, 2)); // misaligned stack entry
|
||||
if (math.cast(u12, @divExact(raw_offset, 2))) |imm| {
|
||||
break :blk Instruction.LoadStoreOffset.imm(imm);
|
||||
} else |_| {
|
||||
return emit.fail("TODO load/store stack halfword with larger offset", .{});
|
||||
}
|
||||
},
|
||||
.ldr_stack, .str_stack => blk: {
|
||||
const alignment: u32 = switch (load_store_stack.rt.size()) {
|
||||
32 => 4,
|
||||
64 => 8,
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
assert(std.mem.isAlignedGeneric(u32, raw_offset, alignment)); // misaligned stack entry
|
||||
if (math.cast(u12, @divExact(raw_offset, alignment))) |imm| {
|
||||
break :blk Instruction.LoadStoreOffset.imm(imm);
|
||||
} else |_| {
|
||||
return emit.fail("TODO load/store stack with larger offset", .{});
|
||||
}
|
||||
},
|
||||
else => unreachable,
|
||||
};
|
||||
|
||||
switch (tag) {
|
||||
.ldr_stack => try emit.writeInstruction(Instruction.ldr(
|
||||
load_store_stack.rt,
|
||||
Register.sp,
|
||||
offset,
|
||||
)),
|
||||
.ldrb_stack => try emit.writeInstruction(Instruction.ldrb(
|
||||
load_store_stack.rt,
|
||||
Register.sp,
|
||||
offset,
|
||||
)),
|
||||
.ldrh_stack => try emit.writeInstruction(Instruction.ldrh(
|
||||
load_store_stack.rt,
|
||||
Register.sp,
|
||||
offset,
|
||||
)),
|
||||
.str_stack => try emit.writeInstruction(Instruction.str(
|
||||
load_store_stack.rt,
|
||||
Register.sp,
|
||||
offset,
|
||||
)),
|
||||
.strb_stack => try emit.writeInstruction(Instruction.strb(
|
||||
load_store_stack.rt,
|
||||
Register.sp,
|
||||
offset,
|
||||
)),
|
||||
.strh_stack => try emit.writeInstruction(Instruction.strh(
|
||||
load_store_stack.rt,
|
||||
Register.sp,
|
||||
offset,
|
||||
)),
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
fn mirLoadStoreRegister(emit: *Emit, inst: Mir.Inst.Index) !void {
|
||||
const tag = emit.mir.instructions.items(.tag)[inst];
|
||||
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 {
|
||||
switch (tag) {
|
||||
.ldr => try emit.writeInstruction(Instruction.ldr(
|
||||
load_store_register.rt,
|
||||
.{ .register = .{ .rn = load_store_register.rn, .offset = load_store_register.offset } },
|
||||
load_store_register.rn,
|
||||
load_store_register.offset,
|
||||
)),
|
||||
.ldrb => try emit.writeInstruction(Instruction.ldrb(
|
||||
load_store_register.rt,
|
||||
load_store_register.rn,
|
||||
.{ .offset = load_store_register.offset },
|
||||
load_store_register.offset,
|
||||
)),
|
||||
.ldrh => try emit.writeInstruction(Instruction.ldrh(
|
||||
load_store_register.rt,
|
||||
load_store_register.rn,
|
||||
.{ .offset = load_store_register.offset },
|
||||
load_store_register.offset,
|
||||
)),
|
||||
.str => try emit.writeInstruction(Instruction.str(
|
||||
load_store_register.rt,
|
||||
load_store_register.rn,
|
||||
.{ .offset = load_store_register.offset },
|
||||
load_store_register.offset,
|
||||
)),
|
||||
.strb => try emit.writeInstruction(Instruction.strb(
|
||||
load_store_register.rt,
|
||||
load_store_register.rn,
|
||||
.{ .offset = load_store_register.offset },
|
||||
load_store_register.offset,
|
||||
)),
|
||||
.strh => try emit.writeInstruction(Instruction.strh(
|
||||
load_store_register.rt,
|
||||
load_store_register.rn,
|
||||
.{ .offset = load_store_register.offset },
|
||||
load_store_register.offset,
|
||||
)),
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
@@ -56,12 +56,18 @@ pub const Inst = struct {
|
||||
load_memory,
|
||||
/// Load Pair of Registers
|
||||
ldp,
|
||||
/// Pseudo-instruction: Load from stack
|
||||
ldr_stack,
|
||||
/// Load Register
|
||||
// TODO: split into ldr_immediate and ldr_register
|
||||
ldr,
|
||||
/// Pseudo-instruction: Load byte from stack
|
||||
ldrb_stack,
|
||||
/// Load Register Byte
|
||||
// TODO: split into ldrb_immediate and ldrb_register
|
||||
ldrb,
|
||||
/// Pseudo-instruction: Load halfword from stack
|
||||
ldrh_stack,
|
||||
/// Load Register Halfword
|
||||
// TODO: split into ldrh_immediate and ldrh_register
|
||||
ldrh,
|
||||
@@ -79,12 +85,18 @@ pub const Inst = struct {
|
||||
ret,
|
||||
/// Store Pair of Registers
|
||||
stp,
|
||||
/// Pseudo-instruction: Store to stack
|
||||
str_stack,
|
||||
/// Store Register
|
||||
// TODO: split into str_immediate and str_register
|
||||
str,
|
||||
/// Pseudo-instruction: Store byte to stack
|
||||
strb_stack,
|
||||
/// Store Register Byte
|
||||
// TODO: split into strb_immediate and strb_register
|
||||
strb,
|
||||
/// Pseudo-instruction: Store halfword to stack
|
||||
strh_stack,
|
||||
/// Store Register Halfword
|
||||
// TODO: split into strh_immediate and strh_register
|
||||
strh,
|
||||
@@ -175,7 +187,7 @@ pub const Inst = struct {
|
||||
rm: Register,
|
||||
cond: bits.Instruction.Condition,
|
||||
},
|
||||
/// Three registers and a LoadStoreOffset
|
||||
/// Two registers and a LoadStoreOffset
|
||||
///
|
||||
/// Used by e.g. str_register
|
||||
load_store_register: struct {
|
||||
@@ -183,6 +195,13 @@ pub const Inst = struct {
|
||||
rn: Register,
|
||||
offset: bits.Instruction.LoadStoreOffset,
|
||||
},
|
||||
/// A registers and a stack offset
|
||||
///
|
||||
/// Used by e.g. str_register
|
||||
load_store_stack: struct {
|
||||
rt: Register,
|
||||
offset: u32,
|
||||
},
|
||||
/// Three registers and a LoadStorePairOffset
|
||||
///
|
||||
/// Used by e.g. stp
|
||||
|
||||
@@ -742,27 +742,17 @@ pub const Instruction = union(enum) {
|
||||
}
|
||||
|
||||
fn loadLiteral(rt: Register, imm19: u19) Instruction {
|
||||
switch (rt.size()) {
|
||||
32 => {
|
||||
return Instruction{
|
||||
.load_literal = .{
|
||||
.rt = rt.id(),
|
||||
.imm19 = imm19,
|
||||
.opc = 0b00,
|
||||
},
|
||||
};
|
||||
return Instruction{
|
||||
.load_literal = .{
|
||||
.rt = rt.id(),
|
||||
.imm19 = imm19,
|
||||
.opc = switch (rt.size()) {
|
||||
32 => 0b00,
|
||||
64 => 0b01,
|
||||
else => unreachable, // unexpected register size
|
||||
},
|
||||
},
|
||||
64 => {
|
||||
return Instruction{
|
||||
.load_literal = .{
|
||||
.rt = rt.id(),
|
||||
.imm19 = imm19,
|
||||
.opc = 0b01,
|
||||
},
|
||||
};
|
||||
},
|
||||
else => unreachable, // unexpected register size
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn exceptionGeneration(
|
||||
@@ -1001,43 +991,32 @@ pub const Instruction = union(enum) {
|
||||
|
||||
// Load or store register
|
||||
|
||||
pub const LdrArgs = union(enum) {
|
||||
register: struct {
|
||||
rn: Register,
|
||||
offset: LoadStoreOffset = LoadStoreOffset.none,
|
||||
},
|
||||
literal: u19,
|
||||
};
|
||||
|
||||
pub fn ldr(rt: Register, args: LdrArgs) Instruction {
|
||||
switch (args) {
|
||||
.register => |info| return loadStoreRegister(rt, info.rn, info.offset, .ldr),
|
||||
.literal => |literal| return loadLiteral(rt, literal),
|
||||
}
|
||||
pub fn ldrLiteral(rt: Register, literal: u19) Instruction {
|
||||
return loadLiteral(rt, literal);
|
||||
}
|
||||
|
||||
pub fn ldrh(rt: Register, rn: Register, args: StrArgs) Instruction {
|
||||
return loadStoreRegister(rt, rn, args.offset, .ldrh);
|
||||
pub fn ldr(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction {
|
||||
return loadStoreRegister(rt, rn, offset, .ldr);
|
||||
}
|
||||
|
||||
pub fn ldrb(rt: Register, rn: Register, args: StrArgs) Instruction {
|
||||
return loadStoreRegister(rt, rn, args.offset, .ldrb);
|
||||
pub fn ldrh(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction {
|
||||
return loadStoreRegister(rt, rn, offset, .ldrh);
|
||||
}
|
||||
|
||||
pub const StrArgs = struct {
|
||||
offset: LoadStoreOffset = LoadStoreOffset.none,
|
||||
};
|
||||
|
||||
pub fn str(rt: Register, rn: Register, args: StrArgs) Instruction {
|
||||
return loadStoreRegister(rt, rn, args.offset, .str);
|
||||
pub fn ldrb(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction {
|
||||
return loadStoreRegister(rt, rn, offset, .ldrb);
|
||||
}
|
||||
|
||||
pub fn strh(rt: Register, rn: Register, args: StrArgs) Instruction {
|
||||
return loadStoreRegister(rt, rn, args.offset, .strh);
|
||||
pub fn str(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction {
|
||||
return loadStoreRegister(rt, rn, offset, .str);
|
||||
}
|
||||
|
||||
pub fn strb(rt: Register, rn: Register, args: StrArgs) Instruction {
|
||||
return loadStoreRegister(rt, rn, args.offset, .strb);
|
||||
pub fn strh(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction {
|
||||
return loadStoreRegister(rt, rn, offset, .strh);
|
||||
}
|
||||
|
||||
pub fn strb(rt: Register, rn: Register, offset: LoadStoreOffset) Instruction {
|
||||
return loadStoreRegister(rt, rn, offset, .strb);
|
||||
}
|
||||
|
||||
// Load or store pair of registers
|
||||
@@ -1324,47 +1303,47 @@ test "serialize instructions" {
|
||||
.expected = 0b1_00101_00_0000_0000_0000_0000_0000_0100,
|
||||
},
|
||||
.{ // ldr x2, [x1]
|
||||
.inst = Instruction.ldr(.x2, .{ .register = .{ .rn = .x1 } }),
|
||||
.inst = Instruction.ldr(.x2, .x1, Instruction.LoadStoreOffset.none),
|
||||
.expected = 0b11_111_0_01_01_000000000000_00001_00010,
|
||||
},
|
||||
.{ // ldr x2, [x1, #1]!
|
||||
.inst = Instruction.ldr(.x2, .{ .register = .{ .rn = .x1, .offset = Instruction.LoadStoreOffset.imm_pre_index(1) } }),
|
||||
.inst = Instruction.ldr(.x2, .x1, Instruction.LoadStoreOffset.imm_pre_index(1)),
|
||||
.expected = 0b11_111_0_00_01_0_000000001_11_00001_00010,
|
||||
},
|
||||
.{ // ldr x2, [x1], #-1
|
||||
.inst = Instruction.ldr(.x2, .{ .register = .{ .rn = .x1, .offset = Instruction.LoadStoreOffset.imm_post_index(-1) } }),
|
||||
.inst = Instruction.ldr(.x2, .x1, Instruction.LoadStoreOffset.imm_post_index(-1)),
|
||||
.expected = 0b11_111_0_00_01_0_111111111_01_00001_00010,
|
||||
},
|
||||
.{ // ldr x2, [x1], (x3)
|
||||
.inst = Instruction.ldr(.x2, .{ .register = .{ .rn = .x1, .offset = Instruction.LoadStoreOffset.reg(.x3) } }),
|
||||
.inst = Instruction.ldr(.x2, .x1, Instruction.LoadStoreOffset.reg(.x3)),
|
||||
.expected = 0b11_111_0_00_01_1_00011_011_0_10_00001_00010,
|
||||
},
|
||||
.{ // ldr x2, label
|
||||
.inst = Instruction.ldr(.x2, .{ .literal = 0x1 }),
|
||||
.inst = Instruction.ldrLiteral(.x2, 0x1),
|
||||
.expected = 0b01_011_0_00_0000000000000000001_00010,
|
||||
},
|
||||
.{ // ldrh x7, [x4], #0xaa
|
||||
.inst = Instruction.ldrh(.x7, .x4, .{ .offset = Instruction.LoadStoreOffset.imm_post_index(0xaa) }),
|
||||
.inst = Instruction.ldrh(.x7, .x4, Instruction.LoadStoreOffset.imm_post_index(0xaa)),
|
||||
.expected = 0b01_111_0_00_01_0_010101010_01_00100_00111,
|
||||
},
|
||||
.{ // ldrb x9, [x15, #0xff]!
|
||||
.inst = Instruction.ldrb(.x9, .x15, .{ .offset = Instruction.LoadStoreOffset.imm_pre_index(0xff) }),
|
||||
.inst = Instruction.ldrb(.x9, .x15, Instruction.LoadStoreOffset.imm_pre_index(0xff)),
|
||||
.expected = 0b00_111_0_00_01_0_011111111_11_01111_01001,
|
||||
},
|
||||
.{ // str x2, [x1]
|
||||
.inst = Instruction.str(.x2, .x1, .{}),
|
||||
.inst = Instruction.str(.x2, .x1, Instruction.LoadStoreOffset.none),
|
||||
.expected = 0b11_111_0_01_00_000000000000_00001_00010,
|
||||
},
|
||||
.{ // str x2, [x1], (x3)
|
||||
.inst = Instruction.str(.x2, .x1, .{ .offset = Instruction.LoadStoreOffset.reg(.x3) }),
|
||||
.inst = Instruction.str(.x2, .x1, Instruction.LoadStoreOffset.reg(.x3)),
|
||||
.expected = 0b11_111_0_00_00_1_00011_011_0_10_00001_00010,
|
||||
},
|
||||
.{ // strh w0, [x1]
|
||||
.inst = Instruction.strh(.w0, .x1, .{}),
|
||||
.inst = Instruction.strh(.w0, .x1, Instruction.LoadStoreOffset.none),
|
||||
.expected = 0b01_111_0_01_00_000000000000_00001_00000,
|
||||
},
|
||||
.{ // strb w8, [x9]
|
||||
.inst = Instruction.strb(.w8, .x9, .{}),
|
||||
.inst = Instruction.strb(.w8, .x9, Instruction.LoadStoreOffset.none),
|
||||
.expected = 0b00_111_0_01_00_000000000000_01001_01000,
|
||||
},
|
||||
.{ // adr x2, #0x8
|
||||
|
||||
@@ -2041,12 +2041,11 @@ fn createStubHelperPreambleAtom(self: *MachO) !void {
|
||||
.@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_GOT_LOAD_PAGE21),
|
||||
});
|
||||
// ldr x16, [x16, 0]
|
||||
mem.writeIntLittle(u32, atom.code.items[16..][0..4], aarch64.Instruction.ldr(.x16, .{
|
||||
.register = .{
|
||||
.rn = .x16,
|
||||
.offset = aarch64.Instruction.LoadStoreOffset.imm(0),
|
||||
},
|
||||
}).toU32());
|
||||
mem.writeIntLittle(u32, atom.code.items[16..][0..4], aarch64.Instruction.ldr(
|
||||
.x16,
|
||||
.x16,
|
||||
aarch64.Instruction.LoadStoreOffset.imm(0),
|
||||
).toU32());
|
||||
atom.relocs.appendAssumeCapacity(.{
|
||||
.offset = 16,
|
||||
.target = .{ .global = self.undefs.items[self.dyld_stub_binder_index.?].n_strx },
|
||||
@@ -2119,9 +2118,10 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {
|
||||
break :blk try math.cast(u18, div_res);
|
||||
};
|
||||
// ldr w16, literal
|
||||
mem.writeIntLittle(u32, atom.code.items[0..4], aarch64.Instruction.ldr(.w16, .{
|
||||
.literal = literal,
|
||||
}).toU32());
|
||||
mem.writeIntLittle(u32, atom.code.items[0..4], aarch64.Instruction.ldrLiteral(
|
||||
.w16,
|
||||
literal,
|
||||
).toU32());
|
||||
// b disp
|
||||
mem.writeIntLittle(u32, atom.code.items[4..8], aarch64.Instruction.b(0).toU32());
|
||||
atom.relocs.appendAssumeCapacity(.{
|
||||
@@ -2222,12 +2222,11 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {
|
||||
.@"type" = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGE21),
|
||||
});
|
||||
// ldr x16, x16, offset
|
||||
mem.writeIntLittle(u32, atom.code.items[4..8], aarch64.Instruction.ldr(.x16, .{
|
||||
.register = .{
|
||||
.rn = .x16,
|
||||
.offset = aarch64.Instruction.LoadStoreOffset.imm(0),
|
||||
},
|
||||
}).toU32());
|
||||
mem.writeIntLittle(u32, atom.code.items[4..8], aarch64.Instruction.ldr(
|
||||
.x16,
|
||||
.x16,
|
||||
aarch64.Instruction.LoadStoreOffset.imm(0),
|
||||
).toU32());
|
||||
atom.relocs.appendAssumeCapacity(.{
|
||||
.offset = 4,
|
||||
.target = .{ .local = laptr_sym_index },
|
||||
|
||||
Reference in New Issue
Block a user