authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-21 22:48:19+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-21 22:48:19+01:00
log9fd112804fbdeb288b90cf8323d3ebefaa26372f
tree937d9c1192d8b3e67cefba78792756cd8bdbbbe2
parent8ba31ed39a84ba00e85c456e74d0ea4d682d86c0

link: commit missing files


2 files changed, 164 insertions(+), 0 deletions(-)

src/link/aarch64.zig created+106
...@@ -0,0 +1,106 @@
1pub inline fn isArithmeticOp(inst: *const [4]u8) bool {
2 const group_decode = @as(u5, @truncate(inst[3]));
3 return ((group_decode >> 2) == 4);
4}
5
6pub const PageOffsetInstKind = enum {
7 arithmetic,
8 load_store_8,
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,
20 Instruction.load_store_register,
21 ), code),
22 };
23 return switch (inst.load_store_register.size) {
24 0 => if (inst.load_store_register.v == 1) .load_store_128 else .load_store_8,
25 1 => .load_store_16,
26 2 => .load_store_32,
27 3 => .load_store_64,
28 };
29}
30
31pub fn calcPageOffset(kind: PageOffsetInstKind, taddr: u64) !u12 {
32 const narrowed = @as(u12, @truncate(taddr));
33 return switch (kind) {
34 .arithmetic, .load_store_8 => narrowed,
35 .load_store_16 => try math.divExact(u12, narrowed, 2),
36 .load_store_32 => try math.divExact(u12, narrowed, 4),
37 .load_store_64 => try math.divExact(u12, narrowed, 8),
38 .load_store_128 => try math.divExact(u12, narrowed, 16),
39 };
40}
41
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}
67
68pub fn calcNumberOfPages(saddr: u64, taddr: u64) error{Overflow}!i21 {
69 const spage = math.cast(i32, saddr >> 12) orelse return error.Overflow;
70 const tpage = math.cast(i32, taddr >> 12) orelse return error.Overflow;
71 const pages = math.cast(i21, tpage - spage) orelse return error.Overflow;
72 return pages;
73}
74
75pub fn writePages(pages: u21, code: *[4]u8) !void {
76 var inst = Instruction{
77 .pc_relative_address = mem.bytesToValue(std.meta.TagPayload(
78 Instruction,
79 Instruction.pc_relative_address,
80 ), code),
81 };
82 inst.pc_relative_address.immhi = @as(u19, @truncate(pages >> 2));
83 inst.pc_relative_address.immlo = @as(u2, @truncate(pages));
84 mem.writeInt(u32, code, inst.toU32(), .little);
85}
86
87pub fn writeBranchImm(disp: i28, code: *[4]u8) !void {
88 var inst = Instruction{
89 .unconditional_branch_immediate = mem.bytesToValue(std.meta.TagPayload(
90 Instruction,
91 Instruction.unconditional_branch_immediate,
92 ), code),
93 };
94 inst.unconditional_branch_immediate.imm26 = @as(u26, @truncate(@as(u28, @bitCast(disp >> 2))));
95 mem.writeInt(u32, code, inst.toU32(), .little);
96}
97
98const assert = std.debug.assert;
99const bits = @import("../arch/aarch64/bits.zig");
100const builtin = @import("builtin");
101const math = std.math;
102const mem = std.mem;
103const std = @import("std");
104
105pub const Instruction = bits.Instruction;
106pub const Register = bits.Register;
src/link/riscv.zig created+58
...@@ -0,0 +1,58 @@
1pub fn writeSetSub6(comptime op: enum { set, sub }, code: *[1]u8, addend: anytype) void {
2 const mask: u8 = 0b11_000000;
3 const actual: i8 = @truncate(addend);
4 var value: u8 = mem.readInt(u8, code, .little);
5 switch (op) {
6 .set => value = (value & mask) | @as(u8, @bitCast(actual & ~mask)),
7 .sub => value = (value & mask) | (@as(u8, @bitCast(@as(i8, @bitCast(value)) -| actual)) & ~mask),
8 }
9 mem.writeInt(u8, code, value, .little);
10}
11
12pub fn writeAddend(
13 comptime Int: type,
14 comptime op: enum { add, sub },
15 code: *[@typeInfo(Int).Int.bits / 8]u8,
16 value: anytype,
17) void {
18 var V: Int = mem.readInt(Int, code, .little);
19 const addend: Int = @truncate(value);
20 switch (op) {
21 .add => V +|= addend, // TODO: I think saturating arithmetic is correct here
22 .sub => V -|= addend,
23 }
24 mem.writeInt(Int, code, V, .little);
25}
26
27pub fn writeInstU(code: *[4]u8, value: u32) void {
28 const inst_mask: u32 = 0b00000000000000000000_11111_1111111;
29 const val_mask: u32 = 0xffff_f000;
30 var inst = mem.readInt(u32, code, .little);
31 inst &= inst_mask;
32 const compensated: u32 = @bitCast(@as(i32, @bitCast(value)) + 0x800);
33 inst |= (compensated & val_mask);
34 mem.writeInt(u32, code, inst, .little);
35}
36
37pub fn writeInstI(code: *[4]u8, value: u32) void {
38 const mask: u32 = 0b00000000000_11111_111_11111_1111111;
39 var inst = mem.readInt(u32, code, .little);
40 inst &= mask;
41 inst |= (bitSlice(value, 11, 0) << 20);
42 mem.writeInt(u32, code, inst, .little);
43}
44
45pub fn writeInstS(code: *[4]u8, value: u32) void {
46 const mask: u32 = 0b000000_11111_11111_111_00000_1111111;
47 var inst = mem.readInt(u32, code, .little);
48 inst &= mask;
49 inst |= (bitSlice(value, 11, 5) << 25) | (bitSlice(value, 4, 0) << 7);
50 mem.writeInt(u32, code, inst, .little);
51}
52
53fn bitSlice(value: anytype, high: std.math.Log2Int(@TypeOf(value)), low: std.math.Log2Int(@TypeOf(value))) @TypeOf(value) {
54 return (value >> low) & ((@as(@TypeOf(value), 1) << (high - low + 1)) - 1);
55}
56
57const mem = std.mem;
58const std = @import("std");