diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-02-21 22:48:19 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-02-21 22:48:19 +0100 |
| commit | 9fd112804fbdeb288b90cf8323d3ebefaa26372f (patch) | |
| tree | 937d9c1192d8b3e67cefba78792756cd8bdbbbe2 /src/link/aarch64.zig | |
| parent | 8ba31ed39a84ba00e85c456e74d0ea4d682d86c0 (diff) | |
| download | zig-9fd112804fbdeb288b90cf8323d3ebefaa26372f.tar.gz zig-9fd112804fbdeb288b90cf8323d3ebefaa26372f.zip | |
link: commit missing files
Diffstat (limited to 'src/link/aarch64.zig')
| -rw-r--r-- | src/link/aarch64.zig | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/src/link/aarch64.zig b/src/link/aarch64.zig new file mode 100644 index 0000000000..a9295026d2 --- /dev/null +++ b/src/link/aarch64.zig @@ -0,0 +1,106 @@ +pub inline fn isArithmeticOp(inst: *const [4]u8) bool { + const group_decode = @as(u5, @truncate(inst[3])); + return ((group_decode >> 2) == 4); +} + +pub const PageOffsetInstKind = enum { + arithmetic, + load_store_8, + load_store_16, + load_store_32, + load_store_64, + load_store_128, +}; + +pub fn classifyInst(code: *const [4]u8) PageOffsetInstKind { + if (isArithmeticOp(code)) return .arithmetic; + const inst = Instruction{ + .load_store_register = mem.bytesToValue(std.meta.TagPayload( + Instruction, + Instruction.load_store_register, + ), code), + }; + return switch (inst.load_store_register.size) { + 0 => if (inst.load_store_register.v == 1) .load_store_128 else .load_store_8, + 1 => .load_store_16, + 2 => .load_store_32, + 3 => .load_store_64, + }; +} + +pub fn calcPageOffset(kind: PageOffsetInstKind, taddr: u64) !u12 { + const narrowed = @as(u12, @truncate(taddr)); + return switch (kind) { + .arithmetic, .load_store_8 => narrowed, + .load_store_16 => try math.divExact(u12, narrowed, 2), + .load_store_32 => try math.divExact(u12, narrowed, 4), + .load_store_64 => try math.divExact(u12, narrowed, 8), + .load_store_128 => try math.divExact(u12, narrowed, 16), + }; +} + +pub fn writePageOffset(kind: PageOffsetInstKind, taddr: u64, code: *[4]u8) !void { + const value = try calcPageOffset(kind, taddr); + switch (kind) { + .arithmetic => { + var inst = Instruction{ + .add_subtract_immediate = mem.bytesToValue(std.meta.TagPayload( + Instruction, + Instruction.add_subtract_immediate, + ), code), + }; + inst.add_subtract_immediate.imm12 = value; + mem.writeInt(u32, code, inst.toU32(), .little); + }, + else => { + var inst: Instruction = .{ + .load_store_register = mem.bytesToValue(std.meta.TagPayload( + Instruction, + Instruction.load_store_register, + ), code), + }; + inst.load_store_register.offset = value; + mem.writeInt(u32, code, inst.toU32(), .little); + }, + } +} + +pub fn calcNumberOfPages(saddr: u64, taddr: u64) error{Overflow}!i21 { + const spage = math.cast(i32, saddr >> 12) orelse return error.Overflow; + const tpage = math.cast(i32, taddr >> 12) orelse return error.Overflow; + const pages = math.cast(i21, tpage - spage) orelse return error.Overflow; + return pages; +} + +pub fn writePages(pages: u21, code: *[4]u8) !void { + var inst = Instruction{ + .pc_relative_address = mem.bytesToValue(std.meta.TagPayload( + Instruction, + Instruction.pc_relative_address, + ), code), + }; + inst.pc_relative_address.immhi = @as(u19, @truncate(pages >> 2)); + inst.pc_relative_address.immlo = @as(u2, @truncate(pages)); + mem.writeInt(u32, code, inst.toU32(), .little); +} + +pub fn writeBranchImm(disp: i28, code: *[4]u8) !void { + var inst = Instruction{ + .unconditional_branch_immediate = mem.bytesToValue(std.meta.TagPayload( + Instruction, + Instruction.unconditional_branch_immediate, + ), code), + }; + inst.unconditional_branch_immediate.imm26 = @as(u26, @truncate(@as(u28, @bitCast(disp >> 2)))); + mem.writeInt(u32, code, inst.toU32(), .little); +} + +const assert = std.debug.assert; +const bits = @import("../arch/aarch64/bits.zig"); +const builtin = @import("builtin"); +const math = std.math; +const mem = std.mem; +const std = @import("std"); + +pub const Instruction = bits.Instruction; +pub const Register = bits.Register; |
