authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-03-08 14:13:30+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-03-08 22:46:17+01:00
log109d2321b0d92f20e75dcc0b7074026cefe1090e
tree428ff4af212fdabbe69c552b6358d351c851eb27
parentc1dbf01aa3e7ee1922762e6f9b86b2ad4c4a7e6f

link: refactor common aarch64 helpers


6 files changed, 71 insertions(+), 100 deletions(-)

src/link/Elf/Atom.zig+18-15
...@@ -1689,7 +1689,7 @@ const aarch64 = struct {...@@ -1689,7 +1689,7 @@ const aarch64 = struct {
1689 });1689 });
1690 return;1690 return;
1691 };1691 };
1692 try aarch64_util.writeBranchImm(disp, code[r_offset..][0..4]);1692 aarch64_util.writeBranchImm(disp, code[r_offset..][0..4]);
1693 },1693 },
16941694
1695 .ADR_PREL_PG_HI21 => {1695 .ADR_PREL_PG_HI21 => {
...@@ -1697,14 +1697,14 @@ const aarch64 = struct {...@@ -1697,14 +1697,14 @@ const aarch64 = struct {
1697 const saddr = @as(u64, @intCast(P));1697 const saddr = @as(u64, @intCast(P));
1698 const taddr = @as(u64, @intCast(S + A));1698 const taddr = @as(u64, @intCast(S + A));
1699 const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr)));1699 const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr)));
1700 try aarch64_util.writePages(pages, code[r_offset..][0..4]);1700 aarch64_util.writeAdrpInst(pages, code[r_offset..][0..4]);
1701 },1701 },
17021702
1703 .ADR_GOT_PAGE => if (target.flags.has_got) {1703 .ADR_GOT_PAGE => if (target.flags.has_got) {
1704 const saddr = @as(u64, @intCast(P));1704 const saddr = @as(u64, @intCast(P));
1705 const taddr = @as(u64, @intCast(G + GOT + A));1705 const taddr = @as(u64, @intCast(G + GOT + A));
1706 const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr)));1706 const pages = @as(u21, @bitCast(try aarch64_util.calcNumberOfPages(saddr, taddr)));
1707 try aarch64_util.writePages(pages, code[r_offset..][0..4]);1707 aarch64_util.writeAdrpInst(pages, code[r_offset..][0..4]);
1708 } else {1708 } else {
1709 // TODO: relax1709 // TODO: relax
1710 var err = try elf_file.addErrorWithNotes(1);1710 var err = try elf_file.addErrorWithNotes(1);
...@@ -1719,10 +1719,14 @@ const aarch64 = struct {...@@ -1719,10 +1719,14 @@ const aarch64 = struct {
1719 .LD64_GOT_LO12_NC => {1719 .LD64_GOT_LO12_NC => {
1720 assert(target.flags.has_got);1720 assert(target.flags.has_got);
1721 const taddr = @as(u64, @intCast(G + GOT + A));1721 const taddr = @as(u64, @intCast(G + GOT + A));
1722 try aarch64_util.writePageOffset(.load_store_64, taddr, code[r_offset..][0..4]);1722 aarch64_util.writeLoadStoreRegInst(@divExact(@as(u12, @truncate(taddr)), 8), code[rel.r_offset..][0..4]);
1723 },
1724
1725 .ADD_ABS_LO12_NC => {
1726 const taddr = @as(u64, @intCast(S + A));
1727 aarch64_util.writeAddImmInst(@truncate(taddr), code[rel.r_offset..][0..4]);
1723 },1728 },
17241729
1725 .ADD_ABS_LO12_NC,
1726 .LDST8_ABS_LO12_NC,1730 .LDST8_ABS_LO12_NC,
1727 .LDST16_ABS_LO12_NC,1731 .LDST16_ABS_LO12_NC,
1728 .LDST32_ABS_LO12_NC,1732 .LDST32_ABS_LO12_NC,
...@@ -1731,27 +1735,26 @@ const aarch64 = struct {...@@ -1731,27 +1735,26 @@ const aarch64 = struct {
1731 => {1735 => {
1732 // TODO: NC means no overflow check1736 // TODO: NC means no overflow check
1733 const taddr = @as(u64, @intCast(S + A));1737 const taddr = @as(u64, @intCast(S + A));
1734 const kind: aarch64_util.PageOffsetInstKind = switch (r_type) {1738 const offset: u12 = switch (r_type) {
1735 .ADD_ABS_LO12_NC => .arithmetic,1739 .LDST8_ABS_LO12_NC => @truncate(taddr),
1736 .LDST8_ABS_LO12_NC => .load_store_8,1740 .LDST16_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 2),
1737 .LDST16_ABS_LO12_NC => .load_store_16,1741 .LDST32_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 4),
1738 .LDST32_ABS_LO12_NC => .load_store_32,1742 .LDST64_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 8),
1739 .LDST64_ABS_LO12_NC => .load_store_64,1743 .LDST128_ABS_LO12_NC => @divExact(@as(u12, @truncate(taddr)), 16),
1740 .LDST128_ABS_LO12_NC => .load_store_128,
1741 else => unreachable,1744 else => unreachable,
1742 };1745 };
1743 try aarch64_util.writePageOffset(kind, taddr, code[r_offset..][0..4]);1746 aarch64_util.writeLoadStoreRegInst(offset, code[rel.r_offset..][0..4]);
1744 },1747 },
17451748
1746 .TLSLE_ADD_TPREL_HI12 => {1749 .TLSLE_ADD_TPREL_HI12 => {
1747 const value = math.cast(i12, (S + A - TP) >> 12) orelse1750 const value = math.cast(i12, (S + A - TP) >> 12) orelse
1748 return error.Overflow;1751 return error.Overflow;
1749 try aarch64_util.writeAddInst(@bitCast(value), code[rel.r_offset..][0..4]);1752 aarch64_util.writeAddImmInst(@bitCast(value), code[rel.r_offset..][0..4]);
1750 },1753 },
17511754
1752 .TLSLE_ADD_TPREL_LO12_NC => {1755 .TLSLE_ADD_TPREL_LO12_NC => {
1753 const value: i12 = @truncate(S + A - TP);1756 const value: i12 = @truncate(S + A - TP);
1754 try aarch64_util.writeAddInst(@bitCast(value), code[rel.r_offset..][0..4]);1757 aarch64_util.writeAddImmInst(@bitCast(value), code[rel.r_offset..][0..4]);
1755 },1758 },
17561759
1757 else => try atom.reportUnhandledRelocError(rel, elf_file),1760 else => try atom.reportUnhandledRelocError(rel, elf_file),
src/link/Elf/synthetic_sections.zig+6-5
...@@ -1028,8 +1028,8 @@ pub const PltSection = struct {...@@ -1028,8 +1028,8 @@ pub const PltSection = struct {
1028 // TODO: relax if possible1028 // TODO: relax if possible
1029 // .got.plt[2]1029 // .got.plt[2]
1030 const pages = try aarch64_util.calcNumberOfPages(plt_addr + 4, got_plt_addr + 16);1030 const pages = try aarch64_util.calcNumberOfPages(plt_addr + 4, got_plt_addr + 16);
1031 const ldr_off = try aarch64_util.calcPageOffset(.load_store_64, got_plt_addr + 16);1031 const ldr_off = try math.divExact(u12, @truncate(got_plt_addr + 16), 8);
1032 const add_off = try aarch64_util.calcPageOffset(.arithmetic, got_plt_addr + 16);1032 const add_off: u12 = @truncate(got_plt_addr + 16);
10331033
1034 const preamble = &[_]Instruction{1034 const preamble = &[_]Instruction{
1035 Instruction.stp(1035 Instruction.stp(
...@@ -1057,8 +1057,8 @@ pub const PltSection = struct {...@@ -1057,8 +1057,8 @@ pub const PltSection = struct {
1057 const target_addr = sym.gotPltAddress(elf_file);1057 const target_addr = sym.gotPltAddress(elf_file);
1058 const source_addr = sym.pltAddress(elf_file);1058 const source_addr = sym.pltAddress(elf_file);
1059 const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr);1059 const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr);
1060 const ldr_off = try aarch64_util.calcPageOffset(.load_store_64, target_addr);1060 const ldr_off = try math.divExact(u12, @truncate(target_addr), 8);
1061 const add_off = try aarch64_util.calcPageOffset(.arithmetic, target_addr);1061 const add_off: u12 = @truncate(target_addr);
1062 const insts = &[_]Instruction{1062 const insts = &[_]Instruction{
1063 Instruction.adrp(.x16, pages),1063 Instruction.adrp(.x16, pages),
1064 Instruction.ldr(.x17, .x16, Instruction.LoadStoreOffset.imm(ldr_off)),1064 Instruction.ldr(.x17, .x16, Instruction.LoadStoreOffset.imm(ldr_off)),
...@@ -1202,7 +1202,7 @@ pub const PltGotSection = struct {...@@ -1202,7 +1202,7 @@ pub const PltGotSection = struct {
1202 const target_addr = sym.gotAddress(elf_file);1202 const target_addr = sym.gotAddress(elf_file);
1203 const source_addr = sym.pltGotAddress(elf_file);1203 const source_addr = sym.pltGotAddress(elf_file);
1204 const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr);1204 const pages = try aarch64_util.calcNumberOfPages(source_addr, target_addr);
1205 const off = try aarch64_util.calcPageOffset(.load_store_64, target_addr);1205 const off = try math.divExact(u12, @truncate(target_addr), 8);
1206 const insts = &[_]Instruction{1206 const insts = &[_]Instruction{
1207 Instruction.adrp(.x16, pages),1207 Instruction.adrp(.x16, pages),
1208 Instruction.ldr(.x17, .x16, Instruction.LoadStoreOffset.imm(off)),1208 Instruction.ldr(.x17, .x16, Instruction.LoadStoreOffset.imm(off)),
...@@ -1758,6 +1758,7 @@ fn writeInt(value: anytype, elf_file: *Elf, writer: anytype) !void {...@@ -1758,6 +1758,7 @@ fn writeInt(value: anytype, elf_file: *Elf, writer: anytype) !void {
1758const assert = std.debug.assert;1758const assert = std.debug.assert;
1759const builtin = @import("builtin");1759const builtin = @import("builtin");
1760const elf = std.elf;1760const elf = std.elf;
1761const math = std.math;
1761const mem = std.mem;1762const mem = std.mem;
1762const log = std.log.scoped(.link);1763const log = std.log.scoped(.link);
1763const relocation = @import("relocation.zig");1764const relocation = @import("relocation.zig");
src/link/MachO/Atom.zig+25-7
...@@ -700,7 +700,7 @@ fn resolveRelocInner(...@@ -700,7 +700,7 @@ fn resolveRelocInner(
700 const S_: i64 = @intCast(thunk.getTargetAddress(rel.target, macho_file));700 const S_: i64 = @intCast(thunk.getTargetAddress(rel.target, macho_file));
701 break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow;701 break :blk math.cast(i28, S_ + A - P) orelse return error.Overflow;
702 };702 };
703 try aarch64.writeBranchImm(disp, code[rel_offset..][0..4]);703 aarch64.writeBranchImm(disp, code[rel_offset..][0..4]);
704 },704 },
705 else => unreachable,705 else => unreachable,
706 }706 }
...@@ -771,7 +771,7 @@ fn resolveRelocInner(...@@ -771,7 +771,7 @@ fn resolveRelocInner(
771 break :target math.cast(u64, target) orelse return error.Overflow;771 break :target math.cast(u64, target) orelse return error.Overflow;
772 };772 };
773 const pages = @as(u21, @bitCast(try aarch64.calcNumberOfPages(source, target)));773 const pages = @as(u21, @bitCast(try aarch64.calcNumberOfPages(source, target)));
774 try aarch64.writePages(pages, code[rel_offset..][0..4]);774 aarch64.writeAdrpInst(pages, code[rel_offset..][0..4]);
775 },775 },
776776
777 .pageoff => {777 .pageoff => {
...@@ -780,8 +780,26 @@ fn resolveRelocInner(...@@ -780,8 +780,26 @@ fn resolveRelocInner(
780 assert(!rel.meta.pcrel);780 assert(!rel.meta.pcrel);
781 const target = math.cast(u64, S + A) orelse return error.Overflow;781 const target = math.cast(u64, S + A) orelse return error.Overflow;
782 const inst_code = code[rel_offset..][0..4];782 const inst_code = code[rel_offset..][0..4];
783 const kind = aarch64.classifyInst(inst_code);783 if (aarch64.isArithmeticOp(inst_code)) {
784 try aarch64.writePageOffset(kind, target, inst_code);784 aarch64.writeAddImmInst(@truncate(target), inst_code);
785 } else {
786 var inst = aarch64.Instruction{
787 .load_store_register = mem.bytesToValue(std.meta.TagPayload(
788 aarch64.Instruction,
789 aarch64.Instruction.load_store_register,
790 ), inst_code),
791 };
792 inst.load_store_register.offset = switch (inst.load_store_register.size) {
793 0 => if (inst.load_store_register.v == 1)
794 try math.divExact(u12, @truncate(target), 16)
795 else
796 @truncate(target),
797 1 => try math.divExact(u12, @truncate(target), 2),
798 2 => try math.divExact(u12, @truncate(target), 4),
799 3 => try math.divExact(u12, @truncate(target), 8),
800 };
801 try writer.writeInt(u32, inst.toU32(), .little);
802 }
785 },803 },
786804
787 .got_load_pageoff => {805 .got_load_pageoff => {
...@@ -789,7 +807,7 @@ fn resolveRelocInner(...@@ -789,7 +807,7 @@ fn resolveRelocInner(
789 assert(rel.meta.length == 2);807 assert(rel.meta.length == 2);
790 assert(!rel.meta.pcrel);808 assert(!rel.meta.pcrel);
791 const target = math.cast(u64, G + A) orelse return error.Overflow;809 const target = math.cast(u64, G + A) orelse return error.Overflow;
792 try aarch64.writePageOffset(.load_store_64, target, code[rel_offset..][0..4]);810 aarch64.writeLoadStoreRegInst(try math.divExact(u12, @truncate(target), 8), code[rel_offset..][0..4]);
793 },811 },
794812
795 .tlvp_pageoff => {813 .tlvp_pageoff => {
...@@ -841,7 +859,7 @@ fn resolveRelocInner(...@@ -841,7 +859,7 @@ fn resolveRelocInner(
841 .load_store_register = .{859 .load_store_register = .{
842 .rt = reg_info.rd,860 .rt = reg_info.rd,
843 .rn = reg_info.rn,861 .rn = reg_info.rn,
844 .offset = try aarch64.calcPageOffset(.load_store_64, target),862 .offset = try math.divExact(u12, @truncate(target), 8),
845 .opc = 0b01,863 .opc = 0b01,
846 .op1 = 0b01,864 .op1 = 0b01,
847 .v = 0,865 .v = 0,
...@@ -851,7 +869,7 @@ fn resolveRelocInner(...@@ -851,7 +869,7 @@ fn resolveRelocInner(
851 .add_subtract_immediate = .{869 .add_subtract_immediate = .{
852 .rd = reg_info.rd,870 .rd = reg_info.rd,
853 .rn = reg_info.rn,871 .rn = reg_info.rn,
854 .imm12 = try aarch64.calcPageOffset(.arithmetic, target),872 .imm12 = @truncate(target),
855 .sh = 0,873 .sh = 0,
856 .s = 0,874 .s = 0,
857 .op = 0,875 .op = 0,
src/link/MachO/synthetic.zig+5-5
...@@ -269,7 +269,7 @@ pub const StubsSection = struct {...@@ -269,7 +269,7 @@ pub const StubsSection = struct {
269 // TODO relax if possible269 // TODO relax if possible
270 const pages = try aarch64.calcNumberOfPages(source, target);270 const pages = try aarch64.calcNumberOfPages(source, target);
271 try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);271 try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);
272 const off = try aarch64.calcPageOffset(.load_store_64, target);272 const off = try math.divExact(u12, @truncate(target), 8);
273 try writer.writeInt(273 try writer.writeInt(
274 u32,274 u32,
275 aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),275 aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),
...@@ -413,7 +413,7 @@ pub const StubsHelperSection = struct {...@@ -413,7 +413,7 @@ pub const StubsHelperSection = struct {
413 // TODO relax if possible413 // TODO relax if possible
414 const pages = try aarch64.calcNumberOfPages(sect.addr, dyld_private_addr);414 const pages = try aarch64.calcNumberOfPages(sect.addr, dyld_private_addr);
415 try writer.writeInt(u32, aarch64.Instruction.adrp(.x17, pages).toU32(), .little);415 try writer.writeInt(u32, aarch64.Instruction.adrp(.x17, pages).toU32(), .little);
416 const off = try aarch64.calcPageOffset(.arithmetic, dyld_private_addr);416 const off: u12 = @truncate(dyld_private_addr);
417 try writer.writeInt(u32, aarch64.Instruction.add(.x17, .x17, off, false).toU32(), .little);417 try writer.writeInt(u32, aarch64.Instruction.add(.x17, .x17, off, false).toU32(), .little);
418 }418 }
419 try writer.writeInt(u32, aarch64.Instruction.stp(419 try writer.writeInt(u32, aarch64.Instruction.stp(
...@@ -426,7 +426,7 @@ pub const StubsHelperSection = struct {...@@ -426,7 +426,7 @@ pub const StubsHelperSection = struct {
426 // TODO relax if possible426 // TODO relax if possible
427 const pages = try aarch64.calcNumberOfPages(sect.addr + 12, dyld_stub_binder_addr);427 const pages = try aarch64.calcNumberOfPages(sect.addr + 12, dyld_stub_binder_addr);
428 try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);428 try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);
429 const off = try aarch64.calcPageOffset(.load_store_64, dyld_stub_binder_addr);429 const off = try math.divExact(u12, @truncate(dyld_stub_binder_addr), 8);
430 try writer.writeInt(u32, aarch64.Instruction.ldr(430 try writer.writeInt(u32, aarch64.Instruction.ldr(
431 .x16,431 .x16,
432 .x16,432 .x16,
...@@ -681,7 +681,7 @@ pub const ObjcStubsSection = struct {...@@ -681,7 +681,7 @@ pub const ObjcStubsSection = struct {
681 const source = addr;681 const source = addr;
682 const pages = try aarch64.calcNumberOfPages(source, target);682 const pages = try aarch64.calcNumberOfPages(source, target);
683 try writer.writeInt(u32, aarch64.Instruction.adrp(.x1, pages).toU32(), .little);683 try writer.writeInt(u32, aarch64.Instruction.adrp(.x1, pages).toU32(), .little);
684 const off = try aarch64.calcPageOffset(.load_store_64, target);684 const off = try math.divExact(u12, @truncate(target), 8);
685 try writer.writeInt(685 try writer.writeInt(
686 u32,686 u32,
687 aarch64.Instruction.ldr(.x1, .x1, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),687 aarch64.Instruction.ldr(.x1, .x1, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),
...@@ -694,7 +694,7 @@ pub const ObjcStubsSection = struct {...@@ -694,7 +694,7 @@ pub const ObjcStubsSection = struct {
694 const source = addr + 2 * @sizeOf(u32);694 const source = addr + 2 * @sizeOf(u32);
695 const pages = try aarch64.calcNumberOfPages(source, target);695 const pages = try aarch64.calcNumberOfPages(source, target);
696 try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);696 try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);
697 const off = try aarch64.calcPageOffset(.load_store_64, target);697 const off = try math.divExact(u12, @truncate(target), 8);
698 try writer.writeInt(698 try writer.writeInt(
699 u32,699 u32,
700 aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),700 aarch64.Instruction.ldr(.x16, .x16, aarch64.Instruction.LoadStoreOffset.imm(off)).toU32(),
src/link/MachO/thunks.zig+1-1
...@@ -101,7 +101,7 @@ pub const Thunk = struct {...@@ -101,7 +101,7 @@ pub const Thunk = struct {
101 const taddr = sym.getAddress(.{}, macho_file);101 const taddr = sym.getAddress(.{}, macho_file);
102 const pages = try aarch64.calcNumberOfPages(saddr, taddr);102 const pages = try aarch64.calcNumberOfPages(saddr, taddr);
103 try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);103 try writer.writeInt(u32, aarch64.Instruction.adrp(.x16, pages).toU32(), .little);
104 const off = try aarch64.calcPageOffset(.arithmetic, taddr);104 const off: u12 = @truncate(taddr);
105 try writer.writeInt(u32, aarch64.Instruction.add(.x16, .x16, off, false).toU32(), .little);105 try writer.writeInt(u32, aarch64.Instruction.add(.x16, .x16, off, false).toU32(), .little);
106 try writer.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little);106 try writer.writeInt(u32, aarch64.Instruction.br(.x16).toU32(), .little);
107 }107 }
src/link/aarch64.zig+16-67
...@@ -3,66 +3,26 @@ pub inline fn isArithmeticOp(inst: *const [4]u8) bool {...@@ -3,66 +3,26 @@ pub inline fn isArithmeticOp(inst: *const [4]u8) bool {
3 return ((group_decode >> 2) == 4);3 return ((group_decode >> 2) == 4);
4}4}
55
6pub const PageOffsetInstKind = enum {6pub fn writeAddImmInst(value: u12, code: *[4]u8) void {
7 arithmetic,7 var inst = Instruction{
8 load_store_8,8 .add_subtract_immediate = mem.bytesToValue(std.meta.TagPayload(
9 load_store_16,
10 load_store_32,
11 load_store_64,
12 load_store_128,
13};
14
15pub fn classifyInst(code: *const [4]u8) PageOffsetInstKind {
16 if (isArithmeticOp(code)) return .arithmetic;
17 const inst = Instruction{
18 .load_store_register = mem.bytesToValue(std.meta.TagPayload(
19 Instruction,9 Instruction,
20 Instruction.load_store_register,10 Instruction.add_subtract_immediate,
21 ), code),11 ), code),
22 };12 };
23 return switch (inst.load_store_register.size) {13 inst.add_subtract_immediate.imm12 = value;
24 0 => if (inst.load_store_register.v == 1) .load_store_128 else .load_store_8,14 mem.writeInt(u32, code, inst.toU32(), .little);
25 1 => .load_store_16,
26 2 => .load_store_32,
27 3 => .load_store_64,
28 };
29}15}
3016
31pub fn calcPageOffset(kind: PageOffsetInstKind, taddr: u64) !u12 {17pub fn writeLoadStoreRegInst(value: u12, code: *[4]u8) void {
32 const narrowed = @as(u12, @truncate(taddr));18 var inst: Instruction = .{
33 return switch (kind) {19 .load_store_register = mem.bytesToValue(std.meta.TagPayload(
34 .arithmetic, .load_store_8 => narrowed,20 Instruction,
35 .load_store_16 => try math.divExact(u12, narrowed, 2),21 Instruction.load_store_register,
36 .load_store_32 => try math.divExact(u12, narrowed, 4),22 ), code),
37 .load_store_64 => try math.divExact(u12, narrowed, 8),
38 .load_store_128 => try math.divExact(u12, narrowed, 16),
39 };23 };
40}24 inst.load_store_register.offset = value;
4125 mem.writeInt(u32, code, inst.toU32(), .little);
42pub fn writePageOffset(kind: PageOffsetInstKind, taddr: u64, code: *[4]u8) !void {
43 const value = try calcPageOffset(kind, taddr);
44 switch (kind) {
45 .arithmetic => {
46 var inst = Instruction{
47 .add_subtract_immediate = mem.bytesToValue(std.meta.TagPayload(
48 Instruction,
49 Instruction.add_subtract_immediate,
50 ), code),
51 };
52 inst.add_subtract_immediate.imm12 = value;
53 mem.writeInt(u32, code, inst.toU32(), .little);
54 },
55 else => {
56 var inst: Instruction = .{
57 .load_store_register = mem.bytesToValue(std.meta.TagPayload(
58 Instruction,
59 Instruction.load_store_register,
60 ), code),
61 };
62 inst.load_store_register.offset = value;
63 mem.writeInt(u32, code, inst.toU32(), .little);
64 },
65 }
66}26}
6727
68pub fn calcNumberOfPages(saddr: u64, taddr: u64) error{Overflow}!i21 {28pub fn calcNumberOfPages(saddr: u64, taddr: u64) error{Overflow}!i21 {
...@@ -72,7 +32,7 @@ pub fn calcNumberOfPages(saddr: u64, taddr: u64) error{Overflow}!i21 {...@@ -72,7 +32,7 @@ pub fn calcNumberOfPages(saddr: u64, taddr: u64) error{Overflow}!i21 {
72 return pages;32 return pages;
73}33}
7434
75pub fn writePages(pages: u21, code: *[4]u8) !void {35pub fn writeAdrpInst(pages: u21, code: *[4]u8) void {
76 var inst = Instruction{36 var inst = Instruction{
77 .pc_relative_address = mem.bytesToValue(std.meta.TagPayload(37 .pc_relative_address = mem.bytesToValue(std.meta.TagPayload(
78 Instruction,38 Instruction,
...@@ -84,7 +44,7 @@ pub fn writePages(pages: u21, code: *[4]u8) !void {...@@ -84,7 +44,7 @@ pub fn writePages(pages: u21, code: *[4]u8) !void {
84 mem.writeInt(u32, code, inst.toU32(), .little);44 mem.writeInt(u32, code, inst.toU32(), .little);
85}45}
8646
87pub fn writeBranchImm(disp: i28, code: *[4]u8) !void {47pub fn writeBranchImm(disp: i28, code: *[4]u8) void {
88 var inst = Instruction{48 var inst = Instruction{
89 .unconditional_branch_immediate = mem.bytesToValue(std.meta.TagPayload(49 .unconditional_branch_immediate = mem.bytesToValue(std.meta.TagPayload(
90 Instruction,50 Instruction,
...@@ -95,17 +55,6 @@ pub fn writeBranchImm(disp: i28, code: *[4]u8) !void {...@@ -95,17 +55,6 @@ pub fn writeBranchImm(disp: i28, code: *[4]u8) !void {
95 mem.writeInt(u32, code, inst.toU32(), .little);55 mem.writeInt(u32, code, inst.toU32(), .little);
96}56}
9757
98pub fn writeAddInst(value: u12, code: *[4]u8) !void {
99 var inst = Instruction{
100 .add_subtract_immediate = mem.bytesToValue(std.meta.TagPayload(
101 Instruction,
102 Instruction.add_subtract_immediate,
103 ), code),
104 };
105 inst.add_subtract_immediate.imm12 = value;
106 mem.writeInt(u32, code, inst.toU32(), .little);
107}
108
109const assert = std.debug.assert;58const assert = std.debug.assert;
110const bits = @import("../arch/aarch64/bits.zig");59const bits = @import("../arch/aarch64/bits.zig");
111const builtin = @import("builtin");60const builtin = @import("builtin");