diff options
author | Mathias Magnusson <mathias@magnusson.space> | 2025-07-01 23:06:06 +0200 |
---|---|---|
committer | Mathias Magnusson <mathias@magnusson.space> | 2025-07-01 23:06:06 +0200 |
commit | 3959256af626292d50d5c05c63073ef28d760546 (patch) | |
tree | d223b13b4f7b375d26bbcef6b8ed0cbfdf22cb48 /src | |
parent | f5036d587fce5fd3e8199acbf3f186987147ec6a (diff) | |
download | huginn-3959256af626292d50d5c05c63073ef28d760546.tar.gz |
make in-memory instruction a little nicer to work with
Diffstat (limited to 'src')
-rw-r--r-- | src/codegen.zig | 68 |
1 files changed, 35 insertions, 33 deletions
diff --git a/src/codegen.zig b/src/codegen.zig index 8c3f592..7ade3fd 100644 --- a/src/codegen.zig +++ b/src/codegen.zig @@ -22,7 +22,7 @@ const Register = enum(u5) { }; /// TODO: Panic on calls that become reserved hints, e.g. addw with rd=x0 -const Instruction = packed union { +const Instruction = union(enum) { r: R, i: I, s: S, @@ -199,7 +199,7 @@ const Instruction = packed union { rd: Register, funct3: u3, rs1: Register, - imm: u12, + imm: i12, fn init(opcode: Opcode, rd: Register, funct3: u3, rs1: Register, imm: i12) Self { return .{ .i = .{ @@ -207,7 +207,7 @@ const Instruction = packed union { .rd = rd, .funct3 = funct3, .rs1 = rs1, - .imm = @bitCast(imm), + .imm = imm, } }; } }; @@ -327,17 +327,16 @@ const Instruction = packed union { funct3: u3, rs1: Register, rs2: Register, - imm11_5: u7, + imm11_5: i7, fn init(opcode: Opcode, funct3: u3, rs1: Register, rs2: Register, imm: i12) Self { - const umm: u12 = @bitCast(imm); return .{ .s = .{ .opcode = opcode, - .imm4_0 = @truncate(umm), + .imm4_0 = @intCast(imm & 0xf), .funct3 = funct3, .rs1 = rs1, .rs2 = rs2, - .imm11_5 = @truncate(umm >> 5), + .imm11_5 = @intCast(imm >> 5), } }; } }; @@ -371,20 +370,19 @@ const Instruction = packed union { rs1: Register, rs2: Register, imm10_5: u6, - imm12: u1, + imm12: i1, fn init(opcode: Opcode, funct3: u3, rs1: Register, rs2: Register, imm: i13) Self { std.debug.assert(imm & 1 == 0); - const umm: u13 = @bitCast(imm); return .{ .b = .{ .opcode = opcode, - .imm11 = @truncate(umm >> 11), - .imm4_1 = @truncate(umm >> 1), + .imm11 = @intCast((imm >> 11) & 1), + .imm4_1 = @intCast((imm >> 1) & 0xf), .funct3 = funct3, .rs1 = rs1, .rs2 = rs2, - .imm10_5 = @truncate(umm >> 5), - .imm12 = @truncate(umm >> 12), + .imm10_5 = @intCast((imm >> 5) & 0x3f), + .imm12 = @intCast(imm >> 12), } }; } }; @@ -440,13 +438,13 @@ const Instruction = packed union { const U = packed struct(u32) { opcode: Opcode, rd: Register, - imm12_31: u20, + imm12_31: i20, fn init(opcode: Opcode, rd: Register, imm: i20) Self { return .{ .u = .{ .opcode = opcode, .rd = rd, - .imm12_31 = @bitCast(imm), + .imm12_31 = imm, } }; } }; @@ -467,18 +465,17 @@ const Instruction = packed union { imm12_19: u8, imm11: u1, imm1_10: u10, - imm20: u1, + imm20: i1, fn init(opcode: Opcode, rd: Register, imm: i21) Self { std.debug.assert(imm & 1 == 0); - const umm: u21 = @bitCast(imm); return .{ .j = .{ .opcode = opcode, .rd = rd, - .imm12_19 = @truncate(umm >> 12), - .imm11 = @truncate(umm >> 11), - .imm1_10 = @truncate(umm >> 1), - .imm20 = @intCast(umm >> 20), + .imm12_19 = @intCast((imm >> 12) & 0xff), + .imm11 = @intCast((imm >> 11) & 1), + .imm1_10 = @intCast((imm >> 1) & 0x3ff), + .imm20 = @intCast(imm >> 20), } }; } }; @@ -488,6 +485,12 @@ const Instruction = packed union { return J.init(0b1101111, rd, imm); } + fn encode(self: Self) u32 { + return switch (self) { + inline else => |s| @bitCast(s), + }; + } + const Self = @This(); }; @@ -820,21 +823,20 @@ pub fn create_elf(allocator: Allocator, proc: compile.Procedure) ![]u8 { // TODO: make this less sheiße for (ctx.relocations.items) |relocation| { const instr = &ctx.instructions.items[relocation.instr]; - const opcode: Instruction.Opcode = @truncate(@as(u32, @bitCast(instr.*))); const target: isize = @intCast(ctx.block_starts.items[@intFromEnum(relocation.target)]); const from: isize = @intCast(relocation.instr); - switch (opcode) { - 0b1101111 => { - const jal: Instruction.J = instr.j; - instr.* = .jal(jal.rd, @intCast((target - from) * 4)); + switch (instr.*) { + .j => |j| { + if (j.opcode == 0b1101111) { + instr.* = .jal(j.rd, @intCast((target - from) * 4)); + } else std.debug.panic("Not yet implemented instruction with relocation {}\n", .{instr}); }, - 0b1100011 => { - const b: Instruction.B = instr.b; - if (b.funct3 != 0) - std.debug.panic("Not yet implemented instruction with relocation\n", .{}); - instr.* = .beq(b.rs1, b.rs2, @intCast((target - from) * 4)); + .b => |b| { + if (b.opcode == 0b1100011 and b.funct3 == 0) { + instr.* = .beq(b.rs1, b.rs2, @intCast((target - from) * 4)); + } else std.debug.panic("Not yet implemented instruction with relocation {}\n", .{instr}); }, - else => std.debug.panic("Not yet implemented instruction with relocation\n", .{}), + else => std.debug.panic("Not yet implemented instruction with relocation {}\n", .{instr}), } } @@ -845,7 +847,7 @@ pub fn create_elf(allocator: Allocator, proc: compile.Procedure) ![]u8 { try output_buffer.appendNTimes(undefined, @sizeOf(elf.Elf64_Ehdr) + @sizeOf(elf.Elf64_Phdr)); const output = output_buffer.writer(); for (ctx.instructions.items) |instr| { - try output.writeInt(u32, @bitCast(instr), .little); + try output.writeInt(u32, instr.encode(), .little); } const base_addr = 0x10000000; |